Monday, September 14, 2015

Java enum usages

A major reason to use statically typed languages is the type safety; the ability to catch certain errors at compile/development time.  One of the great Java features which promotes that is enums.  These are a great replacement for things such as static final ints/strings/etc and it supports functionality well beyond straight replacement of those simple types.

You normally think of enums in context like the following;


public class EnumExample1 
{
  enum Color {RED,  YELLOW, GREEN};
 
  public static void main(String[] args) 
  {
    Color c = Color.RED;
    EnumExample1 example1 = new EnumExample1();
    example1.process(c);
  }
 
  void process(Color color)
  {
    switch(color)
    {
      case RED:  
        System.out.println("Stop");
        break;
      case YELLOW: 
        System.out.print("Caution - slow down");
        break;
      case GREEN:   
        System.out.println("Go");
        break;
    }
  }
}

That is well and good but you can do more; you can extend the enum with interfaces or even add methods to individual enum values.

/**
 * Note: Part of an example program for my kids to help them learn programming..
  
 * Interface for gaining access to the value or values assigned to a 
 * playing card.
 *
 */
public interface CardValIntfc 
{
 public abstract int[] getNumericVals();
}


/**
 * Simple representation of a playing cards "value".  
 *
 */
public enum Value implements CardValIntfc 
{
 Ace(1,11),
 Two(2),
 Three(3),
 Four(4),
 Five(5),
 Six(6),
 Seven(7),
 Eight(8),
 Nine(9),
 Ten(10),
 Jack(10),
 Queen(10),
 King(10);
 
 Value(int tmpVal)
 {
  this.val = new int[]{ tmpVal};
 }
 
 Value(int tmpVal1, int tmpVal2)
 {
  this.val = new int[]{ tmpVal1, tmpVal2};
 }
 
 @Override
 public int[] getNumericVals()
 {
  return val;
 }
 int val []; 
}

Enums are immutable but you can either put in static values as shown above or with care you can load data from properties files or even a database.

I find increased usefulness when I work with multiple application code bases and have shared code needing to process enums but the set of values differs (slightly) between the code bases. Below is description of the progressive changes from a simple enum to something more flexible.

A real example I have is where I represent various databases as distinct enum values and have a bunch of non-database specific code which simple needs an enum value to determine what database to use.  Initially just creating a single enum in the shared code worked within a single application.  A trade-off occurs when you move to multiple applications though.  The enum contains values for all  possible databases whether the application needs them all or not; as in a manufacturing app may not need to know about HR. Also, if you need to add a new database, you have to worry about mixing utility jars which may break if not consistent with the enum configuration they were originally compiled against. 

So initially, an enum representing databases might be made up of values like these:

enum Database 
{
  Finance,
  Service,
  HR,
  Manufacturing
}

To get around this; instead of using an explicit enum in the various application specific and shared API's you instead use an interface and combine that with enums defined in each application.


/**
 * A very basic interface; nearly just a "marker interface"
 *  but could provide more functionality if needed.
 */
public interface DatabaseIntfc  
{
 String getEnumName();
}

So the above might reside in a jar like, db-common-utils.jar. If you have, for example, three department type web applications then you would include that jar in each WAR file. If the source for all three web applications were in separate source trees then you likely would define a Database enum in each source tree in the same package but only include the particular items for the databases you need to reference.


enum Database implements DatabaseIntfc
{
  // Only 2 DB systems in use in this application.
  Service,  
  Manufacturing;

  @Override
  public String getEnumName() 
  {
    return this.name();
  } 
   ....
   // utility stuff
 }

Then in each applications code, you can call the shared utility code but pass the enum constant you are interested in. This might look something like:

        OurDBUtil.hasGrant(Database.HR, "all_users", "admin");

With some creativity, it is pretty easy to come up with ways to put these ideas to work in beneficial ways.

I have been focusing mainly on the benefits of using enums but there is also a sort of downside - not really with enums but care must be taken with their usage.  An example which has bitten me is:  With a big ERP system, the end-users said "here are the ONLY values (5) we will ever use for field XYZ."  What about the other 4 values which are valid for the field, I asked?  "We don't ever need to use those"  was the reply.  And in this case, it appeared that an enum was a great way to go - read field text values and directly convert into enums  or specify directly where needed and pass them around without worry of some type of textual typo occurring. This is great until someone puts unsupported values into the database which then results in things going south quickly when the code can't convert the text to a known enum value.  A simple text field may have been more resilient to errors in this case.  Another option would have been to create enums for all *possible* values and then do some semi-intelligent but certainly more graceful error handling if the unexpected values were found during runtime.

Certainly, the enum usages here could be replaced by some simple ideas such as some regular classes and maybe Spring bean (or CDI) type singletons.  What is better?  It depends.. on too many things to make a blanket statement.  Personally, I like to use enums when it makes sense but there are times when it turns out better using an alternative.  So plan on looking at application needs and other criteria to determine what is the best way for the current and possible future circumstances.


Hope you found this interesting and maybe helpful.

God Bless!
Scott




Saturday, September 12, 2015

Active Directory / Oracle - time stamp handling dilema

I recently received another last minute development request.  I'm going to be a little bit vague on some details on purpose - some things can't be shared.

The general problem to solve is:  On a particular administrative action, a user must complete a specific activity within a particular time frame.  If that activity isn't completed then some data is manipulated to force the user to complete the activity in a timely fashion.  If the activity was completed then flags are cleared regarding the condition.

On first pass through prototyping a possible solution, I recognized it isn't quite as straight forward as hoped.

In this case, we handle several pieces of information from different sources (Oracle and Active Directory). One item is an Oracle date/time (sysdate) generated by the administrative transaction.  We save that "transaction timestamp" in Oracle along with a "to be done by" date which is also stored in Oracle. At that same time, an Active Directory field is indirectly updated to the equivalent of "now". This part of the process works ok and there are no real alternatives available at this time.

At this point in the process, an integration runs which looks for administrative transactions that passed or are at the "to be done by" date and therefore should be checked against the user activity to verify they completed their activity.  This involved comparing an Oracle date/time stored in Oracle against Oracle sysdate - which works well enough and has no issue.

Next we get the user specific last transaction timestamp from Active directory which is represented in Active Directory as a "100ns increment from midnight Jan. 1, 1601".  We then normalize the Oracle transaction timestamp to the same representation as the Active Directory timestamp.  Now in a perfect world, if the Active Directory timestamp is newer than the Oracle transactions timestamp - then the user completed what was required and we clear flags and complete the transaction.Otherwise, we flag the user to complete their task.

The are 2 basic problems though; (1) there is an inherent difference between the Oracle date/time and the Active Directory timestamp - possibly due to one or more causes [activities are only semi-coordinated across servers, possible differences in available precision between Oracle date/time and AD timestamp].  (2) There can be minor differences between system times even when using NTP.

The result of these issues is that in some common circumstances, a user is determined to have completed the transaction just because of the time differences occurring because activities are serialized across different systems but using each systems time.  This I can easily see in the test data I generated.  I have not knowingly run into an issue with differences in the actual clocks in this current situation but we have had previous problems with clocks being out-of-sync.

The "cost" in this situation is significantly higher than desirable if users are determined to be "incomplete" when they actually are "complete".  On that same note, for other reasons it is in the organizations best interest to be as accurate as reasonable. 

[edit 2015/10/03]
Sourcing the time stamps only from AD isn't possible - initially I thought maybe it could be. The final solution isn't too hard to implement.  First I had to determine how close my times had to be to meet business needs.  In this case, I determined that the one use case affected would be fine with 10 seconds of accuracy.  The way I implemented that was to take the transaction time and activity time and subtract them.  If you take the absolute value of that and compare it against 10 seconds, I know whether the user met the timing requirement.  Problem solved.  If the 10 second value is externally configurable, I can easily update the behavior as business requirements change.





Thursday, August 27, 2015

Active Directory Account Expiration - Java

I'm having to do some work with Active Directory accounts.  Here are some tidbits I hope are helpful.

In my situation, I am working with pwLastSet and accountExpires data which are both date/time based.

Active Directory(AD) dates in some (all?) cases are not based on the normal "C" based time functions which calculate seconds from midnight, Jan. 1st 1970.  Instead, AD uses the number of 100ns intervals from midnight, Jan. 1st 1601. 

Here is some code which calculates the number of 100ns increments between Jan 1st, 1601 and 24 hours in the future from "now".  This uses the new Java 8 date/time classes.  The initial date uses the UTC timezone and the end date is using the local timezone.  The negative 24 (-24) is because of the "minusHours()" method causing me to need to subtract a negative to get the positive(future) offset.  The duration is straight forward and by getting the seconds and multiplying by 10^7 I get the 100ns increments.  I used Math.round() just to go from double to long.  The resulting value is then usable in a context such as setting an AD account expiration.

     ZonedDateTime start = ZonedDateTime.of(1601, 1,1,0,0,0, 0, ZoneId.of("Z")); // UTC 
     LocalDateTime now = LocalDateTime.now().minusHours(-24);  
     ZonedDateTime end = ZonedDateTime.of(now, ZoneId.of("America/New_York")); // Eastern 
     Duration dur = Duration.between(start,end);  
     // result in # of 100ns increments  
     long expirationIncrements = Math.round(dur.abs().getSeconds() * Math.pow(10,7));   
     return expirationIncrements;  

Using SpringLDAP, the call to set accountExpires looks like this.  Note "expiration" here was a Long which is converted to a String for use with the LDAP API.

     final ModificationItem [] mods = new ModificationItem[]  
         {  
           new ModificationItem(DirContext.REPLACE_ATTRIBUTE, 
               new BasicAttribute("accountExpires", 
                    expiration.toString()))  
         };  
   
     ldapTemplate.modifyAttributes(userDN, mods);  

Hoping Jesus blesses your day today!
Scott