June 17, 2016

Java EE Guardians moving EE 8 forward at JavaOne 2016 San Francisco

The Java EE Guardians is a group of individuals and organizations from all around the world who stand in support of an open standard for Java enterprise development and are committed to moving Java EE forward.  The group started the first quarter of 2016 in response to Oracle's apparent lack of commitment to Java EE 8.  On the Java EE Guardians website, http://javaee-guardians.io, the group has published evidence showing that the activity of EE 8 JSRs lead by Oracle have slowed significantly (Lack of.., 2016).
Sadly, this lack of commitment to Java EE 8 seems to extend to JavaOne 2016 in San Francisco.  The Java EE Guardians have attempted to contact the EE 8 JSRs specification leads about their intentions to present at JavaOne on the progress of their JSRs.  They have either responded in silence or by saying no.  So the Java EE Guardians have rallied the community to make sure EE 8 has a good representation at JavaOne.  The community actions are summarized in the table below, showing the community members who have stepped up and submitted proposals to JavaOne to ensure the JSRs are represented.
If the current situation remains unchanged, it will be the first time active JSR specification leads from the Java steward will not be presenting their progress to the community in such high numbers; an unprecedented, never-before-seen situation in JavaOne history.  We sincerely hope that most, if not all, of the session proposals put forth by the community are accepted if Oracle specification leads do not step up in time.  It is critical for all the people attending JavaOne to know that standards-based Java enterprise development is moving forward.
Table 1: Java EE 8 JSR JavaOne 2016 Session Proposals
Description
Java EE 8 JSR
Version
Specification Lead
JavaOne 2016 Session Proposal
Java™ Platform, Enterprise Edition Specification
8
Linda Demichiel (Oracle)
William Shannon (Oracle)
Java EE 8 Community Panel
  • Reza Rahman
  • Werner Keil (JCP Executive Committee)
  • Michael Remijan
  • Mark Little (Red Hat)
  • Kevin Sutter (IBM)
  • Oracle contacted to participate, no response so far
Aligning Java EE 8 with Java SE 8 - The Missing Links
  • Reza Rahman
  • Ryan Cuprak
  • Michael Remijan
Java EE 8 Recipes
  • Josh Juneau
Rapid Development Tools for Java EE 8
  • Gaurav Gupta
Java™ Servlet Specification
4.0
Edward Burns (Oracle)
Shing Wai Chan (Oracle)
What’s Coming in Servlet 4
  • Murat Yener
  • Alex Theedom
Java™ Message Service (JMS)
2.1
Nigel Deakin (Oracle)
What’s new with JMS 2.1
  • Ivar Grimstad
JMS BOF
  • Ivar Grimstad
JAX-RS: The JavaTM API for RESTful Web Services
2.1
Santiago Pericasgeertsen (Oracle)
Marek Potociar (Oracle)
JAX-RS 2.1
  • Sebastian Daschner
JavaServer Faces (JSF)
2.3
Edward Burns (Oracle)
Manfred Riem (Oracle)
JSF or MVC, What do I Use?
  • Josh Juneau
JSF 2.3 in Action
  • Kito Mann
Model-View-Controller (MVC)
**NEW**
1.0
Santiago Pericasgeertsen (Oracle)
Manfred Riem (Oracle)
What's new with MVC 1.0?
  • Ivar Grimstad
Modern Web Apps with HTML5 Web Components, Polymer, Java EE MVC 1.0 and JAX-RS
  • Kito Mann
JSF or MVC, What do I Use?
  • Josh Juneau
Java Persistence (JPA)
2.1 MR
Linda Demichiel (Oracle)
Lukas Jungmann (Oracle)
What's Next for JPA? (BOF)
  • Patrycja Wegrzynowicz
  • Michael Remijan
Contexts and Dependency Injection (CDI)
2.0
Antoine Sabot-Durand (Red Hat)
CDI 2.0 in live coding
  • Antoine Sabot-Durand
Micro services and more with CDI on Java SE
  • Antoine Sabot-Durand
Mutate Java EE 7 DNA with CDI portable extensions
  • Antoine Sabot-Durand
Java API for JSON Processing (JSON-P)
1.1
Kinman Chung (Oracle)
What's New in JSON-P 1.1?
  • Werner Keil
Java API for JSON Binding (JSON-B)
**NEW*
1.0
Dmitry Kornilov (Oracle)
JSON-B 1.0
  • Dmitry Kornilov (has submitted)
Java™ EE Security API
Alexander Kosowski (Oracle)
What's new with Java EE Security?
  • Ivar Grimstad
  • Werner Keil
Concurrency Utilities for Java EE 1.0
No change from EE 7
Liberating EJB Concurrency Features for the Community
  • Reza Rahman
JavaOne, and similar conferences, are a critical part in keeping Java strong (Krill, 2015).  They help showcase new technologies and the direction of the industry.  They also allow the community to voice how the trends of today will become the standards of tomorrow.  This has been especially true of EE 7, which brought to the community standards for developing with: HTML5, WebSockets, JSON, Messaging, Batch, Concurrency, Dependency Injection, RESTful Web Services, and non-blocking I/O (Krill, 2013).  EE 7 was released in 2013 (JSR 342, 2011) and it has had a lot to celebrate over the last few years.   It has been well supported by the major application server providers and well adopted by the community (Rahman, 2015).  Modern EE 7 servers are lightweight, fast, and quickly evolving to support architectural changes in the industry (Daschner, 2016; JAX Editorial Team, 2016).  EE 8 promises to bring an MVC standard, JSON binding, more support for HTML 5 and HTTP 2, better CDI integration, and more (Gupta, n.d.).  But this won't happen without community involvement organized by strong leadership from Oracle.    
Visit the Java EE Guardians website, http://javaee-guardians.io, or its Google group, https://groups.google.com/forum/#!forum/javaee-guardians, and add your voice in support of Java EE.
References
JSR 366: Java Platform, Enterprise Edition 8 (Java EE 8) Specification. (2014, August 26).  jcp.org. Retrieved June 1, 2016, from https://jcp.org/en/jsr/detail?id=366
JSR 342: JavaTM Platform, Enterprise Edition 7 (Java EE 7) Specification. (2011, March 01).  jcp.org. Retrieved June 1, 2016, from https://www.jcp.org/en/jsr/detail?id=342
Rahman, R. (2015, June, 08). The Ghosts of Java EE 7 in Production: Past, Present and Future.  blogs.oracle.com. Retrieved June 1, 2016, from https://blogs.oracle.com/reza/entry/the_ghosts_of_java_ee
Lack of Java EE 8 Progress. (2016, May). javaee-guardians.io. Retrieved May 31, 2016 from http://javaee-guardians.io/lack-of-java-ee-8-progress/
Krill, P. (2015, October, 23). Java developers carry hopes and fears to JavaOne. infoworld.com. Retrieved June 2, 2016 from http://www.infoworld.com/article/2996549/java/java-developers-carry-hopes-fears-to-javaone.html
Krill, P. (2013, June, 13). 11 hot improvements to Java EE 7. infoworld.com. Retrieved June 2, 2016 from http://www.infoworld.com/article/2606994/java/105268-11-hot-improvements-to-Java-EE-7.html#slide13
Daschner, S. (2016, April, 9). Stop Saying "heavyweight". blog.sebastian-daschner.com. Retrieved April 11, 2016 from https://blog.sebastian-daschner.com/entries/stop_saying_heavyweight
JAX Editorial Team. (2016, May, 19). “Java EE’s heavyweight label is just mythology”. jaxenter.com. Retrieved May 20, 2016 from https://jaxenter.com/java-ees-heavyweight-label-is-just-mythology-126363.html
Gupta, A. (n.d.). Java EE 8 Status. blog.arungupta.me. Retrieved June 1, 2016 from http://blog.arungupta.me/javaee8

June 14, 2016

VBS Script for Outlook Email Message

Simple tip, this Visual Basic (VBS) script is used to open a new Outlook email message and automatically populate to: and subject:.

' Sleep for 3 minutes
WScript.Sleep(1000 * 60 * 30)
Set oolApp = CreateObject("Outlook.Application")
Set email = oolApp.CreateItem(0)
email.Recipients.Add("user@somedomain.org")
email.Subject = "Subject for email"
email.Display()


Enjoy!

April 12, 2016

My TAR incremental backup strategy

Quick tip:

Here is my TAR incremental backup strategy.  I have been using rsync for a long time but recently ran into a number of permission and symlink issues rsync’ing from an Ubuntu guest to a Windows host.

A few comments on the bash script below:

1.    The do_backup() function is a common function and it does all the work of the backup.
2.    The do_backup() function has to take 4 parameters
a.    $1 is the source directory.  This is the directory you want to backup, OR, this is the directory that has stuff in it you want to backup.
b.    $2 is the destination directory.  This directory is relative to ${backupHome}, but still starts with the / character.  This is where you want the TAR balls to end up.
c.    $3 is a name for the backup.  This is used to create the names of the TAR balls and the SNAR indexes.
d.    $4 is a command to run inside the source directory ($1) which will be piped to the `tar` command for backup.
3.    This strategy makes a full backup (level 0) and a single incremental backup (level 1).  The level 1 backup is (correctly) overwritten each time a backup is performed.
4.    A full backup is performed if:
a.    A backup has never been done before
b.    The size of the incremental backup is greater than 10% of the size of the full backup.

Bash script

#!/bin/bash
backupHome=/mnt/hgfs/Backup

#
# First check to see that that backup directory exists.
# If it does, continue. Otherwise, exit with error code.
#
if [ ! -d "${backupHome}" ]; then
        echo "Directory ${backupHome} does NOT exist, exit."
        exit 1;
else
        echo "Directory ${backupHome} exists, continue."
fi

# do_backup "/etc/postfix" "/etc/postfix" "main" 'echo main.cf'
function do_backup {
    local backupSrc=$1
    local backupDst=${backupHome}${2}
    local backupNme=$3
    local backupDir=$4

    local fullSnarFile=${backupDst}/${backupNme}_full.snar
   local fullTarFile=${backupDst}/${backupNme}_full.tar.gz
    local level1SnarFile=${backupDst}/${backupNme}_level_01.snar
    local level1TarFile=${backupDst}/${backupNme}_level_01.tar.gz

    echo "Backup: ${backupNme} from: ${backupSrc} to: ${backupDst}"
    mkdir -p ${backupDst}
    cd ${backupSrc}

    # Check file percentages and see if full backup is needed
    if [ -f ${fullTarFile} ] && [ -f ${level1TarFile} ]
    then
        local fullSize=$(stat -c%s ${fullTarFile})
        echo "  Size of ${fullTarFile} is ${fullSize}"

        local level1Size=$(stat -c%s ${level1TarFile})
        echo "  Size of ${level1TarFile} is ${level1Size}"

        local percentChange=$(echo "scale=2; (${level1Size}/${fullSize}) * 100" | bc)
        percentChange=$(printf "%.0f" ${percentChange})
        echo "  Percent change is ${percentChange}"

        if [ ${percentChange} -gt 10 ]
        then
            echo "  Prepare for a new full backup"
            rm -f ${fullSnarFile}
            rm -f ${level1SnarFile}
            rm -f ${level1TarFile}
        fi
    fi

    # If file does not exist, perform full backup
    if [ ! -f ${fullSnarFile} ]
    then
        echo "  Performing full backup"
        eval ${backupDir} | tar --listed-incremental ${fullSnarFile} -cpzf ${fullTarFile} -T -
    else
        echo "  Performing level 1 backup"
        cp -f ${fullSnarFile} ${level1SnarFile}
        eval ${backupDir} | tar --listed-incremental ${level1SnarFile} -cpzf ${level1TarFile} -T -
    fi
}


Examples

Let’s take a look at a few usage examples.  For these examples, assume that ${backupHome} is /mnt/hgfs/Backup/ like in the script.

Example 1:

do_backup "/home/apache" "/home/apache" "apache" 'echo .'

Example 1 means you want to backup the /home/apache directory to the /mnt/hgfs/Backup/home/apache directory. The parameter “apache” means the following files will be created:

/mnt/hgfs/Backup/home/apache/apache_full.snar
/mnt/hgfs/Backup/home/apache/apache_full.tar.gz
/mnt/hgfs/Backup/home/apache/apache_level_01.snar
/mnt/hgfs/Backup/home/apache/apache_level_01.tar.gz

Finally, ‘echo .’ means the TAR ball will contain everything inside the /home/apache directory

Example 2:

do_backup "/etc/postfix" "/etc/postfix" "main" 'echo main.cf'

Example 2 means you want to backup the /etc/postfix directory to the /mnt/hgfs/Backup/etc/postfix directory. The parameter “main” means the following files will be created:

/mnt/hgfs/Backup/etc/postfix/main_full.snar
/mnt/hgfs/Backup/etc/postfix/main_full.tar.gz
/mnt/hgfs/Backup/etc/postfix/main_level_01.snar
/mnt/hgfs/Backup/etc/postfix/main_level_01.tar.gz

Finally, ‘echo main.cf’ means the TAR ball will ONLY contain the /etc/postfix/main.cf file!

Example 3:

do_backup "/home/michael" "/home/michael" "michael" 'find . -type f -name ".forward" -o -type d -name "cron" -o
-type d -name "Applications" -o -type d -name ".ssh"'

Example 3 means you want to backup the /home/michael directory to the /mnt/hgfs/Backup/home/michael directory. The parameter “michael” means the following files will be created:

/mnt/hgfs/Backup/home/michael/michael_full.snar
/mnt/hgfs/Backup/home/michael/michael_full.tar.gz
/mnt/hgfs/Backup/home/michael/michael_level_01.snar
/mnt/hgfs/Backup/home/michael/michael_level_01.tar.gz

Finally, 'find . -type f -name ".forward" -o -type d -name "cron" –o -type d -name "Applications" -o -type d -name ".ssh"' means the TAR ball will ONLY contain the following:

/home/michael/.forward
/home/michael/cron/
/home/michael/Applications/
/home/michael/.ssh/

Enjoy!

References

Whipp, Paul. (2010, December). Using tar for full and incremental backups. paulwhippconsulting.com. Retrieved April 4, 2016, from http://paulwhippconsulting.com/blog/using-tar-for-full-and-incremental-backups/

February 25, 2016

Reading MANIFEST.MF Values From a JAR File on your Class Path

Abstract
Recently, I was looking at building a simple "about" page for my newest application (See project Riviera, a database versioning source code management tool).  I started to build a properties file Maven would filter values into, but then I realized it was not necessary.  The JAR MANIFEST.MF file had almost all the metadata already.  So all I had to do was read the properties from MANIFEST.MF, which I found more difficult than I thought it should be. Here's my solution.

Code
Listing 1 shows the code.

Listing 1: Code to read MANIFEST.MF from JAR file on the class path

Attributes attributes;
try {
    URL jarURL 
        = this.getClass().getProtectionDomain().getCodeSource().getLocation();
    
    URI manifestUri 
        = new URI(String.format("jar:%s!/%s", jarURL, JarFile.MANIFEST_NAME));
    
    InputStream is 
        = manifestUri.toURL().openStream()
    
    Manifest manifest 
        = new Manifest(is);
    
    attributes 
        = manifest.getMainAttributes();            

    is.close();
} catch (Exception e) {
    attributes = new Attributes();
}

Let's take a look at this code in a bit more detail.

The URI object is the key to being able to read the MANIFEST.MF file from a JAR.  To read the contents of a JAR file, a properly formatted URI string looks like this:

"jar:file:/C:/path/to/file.jar!/META-INF/MANIFEST.MF"

The jar:file and ! parts are required in the URI.  The rest of the URI depends on the specific location of the JAR file on your file system and what file in the JAR you want to stream.  Knowing what file you want to read is a given, but how do you get the fully-qualified location of the JAR file?

It stands to reason that if the JVM is executing code from a class it got from a JAR file then the JVM should be able to tell you where that JAR file is located. After all, the JVM needs to know where the JAR file is in order to load the class!  Turns out its simple to find this information.  You get the fully-qualified location of the JAR file from a class's ProtectionDomain that comes from the JAR file.  Once you have the fully-qualified location, you can build a properly formatted URI string.  Then once you have a URI object, then the magic happens.

From the URI object you can get a URL object by using URI#toUrl().  Then after you have a URL object you get an InputStream to the resource using the URL#openStream() method. Under the covers, the URL object determines it needs a JarURLConnection to open the stream.

Once you have the InputStream, pass it along to the Manifest constructor and you're done!  Use Manifest#getMainAttributes() to get the Attributes and then use Attributes#getValue(key) to get the value you want.

Let's it!  Now you can read the the name/value attributes from the MANIFEST.MF file.

Enjoy!

References
Bozho. (2010, February 16). How to read a file from a jar file?. stackoverflow.com. Retrieved January 27, 2016 from http://stackoverflow.com/questions/2271926/how-to-read-a-file-from-a-jar-file.