Programming – Adams Bros Blog http://blog.adamsbros.org Sat, 12 May 2018 18:23:23 +0000 en-US hourly 1 https://wordpress.org/?v=5.2.2 javascript async and await http://blog.adamsbros.org/2018/05/10/javascript-async-and-await/ http://blog.adamsbros.org/2018/05/10/javascript-async-and-await/#respond Fri, 11 May 2018 02:28:08 +0000 http://blog.adamsbros.org/?p=661 I scratched my head for awhile when switching from promises to await/async. Hopefully this post helps you not need to scratch yours! 😀

Async/await is the same as using promises. It’s just syntactical sugar to make it look synchronous. The javascript engine sees the “await” and stops execution there for you automatically until the promise is resolved/rejected.

I find the javascript promise with ‘.then()’ and ‘.catch()’ is much nicer if you have really simple things to do with the result and the error. But, as soon as you start getting into a bunch of conditionals, from your results, you tend to get a lot of nested promise call statements. So, to save you from promise hell, you just label your function as async, and use the await expression so that you don’t have to be too concerned with promise management. Then hopefully what you do with the final result is simple, and you then resort to using promises. See the testPromise() calls below for examples.

/**
 * @param fail if true, throw an error with a promise.  If false, resolve
 * a delayed response with a promise.
 * @returns {Promise<*>} Always a promise resolve or reject.
 */
function testPromise(fail) {
    if (fail) {
        return Promise.reject(new Error('failed'));
    }
    else {
        return new Promise(resolve => setTimeout(function () {
            resolve('success')
        }, 1000));
    }
}

/**
 * Test calls with promises, awaits, and async.
 *
 * @param fail if true, fail with error.  If false, succeed normally.
 * @returns {Promise<*>} always a promise, as async/await use promises as
 * does Promise.reject and Promise.resolve.
 */
async function testAsync(fail) {
    let result = await testPromise(fail);
    return result;
}

testAsync(true)
    .then(v => console.log('fail: ', v))
    .catch(e => console.log('fail: ', e.message));
testPromise(true)
    .then(v => console.log('fail w/promise: ', v))
    .catch(e => console.log('fail w/promise: ', e.message));

testAsync(false)
    .then(v => console.log('succeed: ', v))
    .catch(e => console.log('succeed: ', e.message));
testPromise(false)
    .then(v => console.log('succeed w/promise: ', v))
    .catch(e => console.log('succeed w/promise: ', e.message));

/**
 * This shows that within an async function you can try/catch instead of
 * then/catch, as long as you use "await".
 *
 * @returns {Promise}
 */
async function testWithTry() {
    try {
        let result = await testPromise(true);
        console.log('fail w/try: ', result);
    } catch (e) {
        console.log('fail w/try: ', e.message)
    }
    try {
        let result = await testPromise(true);
        console.log('fail w/try w/promise: ', result);
    } catch (e) {
        console.log('fail w/try w/promise: ', e.message)
    }

    try {
        let result = await testPromise(false);
        console.log('succeed w/try: ', result);
    } catch (e) {
        console.log('succeed w/try: ', e.message)
    }
    try {
        let result = await testPromise(false);
        console.log('succeed w/try w/promise: ', result);
    } catch (e) {
        console.log('succeed w/try w/promise: ', e.message)
    }
}

testWithTry();
]]>
http://blog.adamsbros.org/2018/05/10/javascript-async-and-await/feed/ 0
Tora Install on Linux Mint 17 http://blog.adamsbros.org/2015/01/05/tora-install-on-linux-mint-17/ http://blog.adamsbros.org/2015/01/05/tora-install-on-linux-mint-17/#comments Mon, 05 Jan 2015 19:25:58 +0000 http://blog.adamsbros.org/?p=562 We need to start by installing the oracle client appropriate for your architecture.  Grab the oracle instant client rpms from oracle’s site.  Then run…

sudo alien --to-deb oracle-instantclient11.2-*.rpm

Patch

Solution found from a tora bug report.

diff -aur tora-2.1.3/src/toextract.h tora-2.1.3patched/src/toextract.h
--- tora-2.1.3/src/toextract.h	2010-02-02 10:25:43.000000000 -0800
+++ tora-2.1.3patched/src/toextract.h	2012-06-22 21:58:45.026286147 -0700
@@ -53,6 +53,7 @@
 #include 
 //Added by qt3to4:
 #include 
+#include 
 
 class QWidget;
 class toConnection;

Build

svn export https://svn.code.sf.net/p/tora/code/tags/tora-2.1.3
 cd tora-2.1.3
 apt install cmake libboost-system1.55-dev libqscintilla2-dev g++
 cmake -DORACLE_PATH_INCLUDES=/usr/include/oracle/11.2/client64 \
-DCMAKE_BUILD_TYPE=Release -DENABLE_PGSQL=false -DENABLE_DB2=false .
 
 patch -p1 # paste above patch in
 
 make
 sudo tar --strip-components 2 -C /usr/local/bin/ -xzvf tora-2.1.3-Linux.tar.gz
]]>
http://blog.adamsbros.org/2015/01/05/tora-install-on-linux-mint-17/feed/ 1
Java Script Quick Start Tips and Best Practises http://blog.adamsbros.org/2014/11/27/java-script-quick-start-tips-and-best-practises/ http://blog.adamsbros.org/2014/11/27/java-script-quick-start-tips-and-best-practises/#respond Thu, 27 Nov 2014 08:40:48 +0000 http://blog.adamsbros.org/?p=532 When not specified, much of this knowledge comes from Java Script Patterns by Stoyan Stefanov, and the JavaScript Pocket Reference (3rd Edition) by David Flanagan.  I personally found the JavaScript Pocket Reference to be the most valuable of the two.

This is by no means a comprehensive java script language overview, but it does provide a good bit of technical information for a beginner in the language.  It mostly just covers some key concepts that can help improve code quality, and some gotchas of the language.  It is recommended you have used Javascript a little bit prior to reading this.

I may update this from time to time.

Code Quality

Maintaining code quality is one of the most important aspects of creating sustainable software.  In this section, we’ll outline a few aspects of JavaScript, which can create gotchas, or can save you from them.

Use Strict

At the beginning of any function, or script, you can put a static string “use strict”.  In the case of older versions of JavaScript, it’s just interpreted as an unassigned string literal.  In the case of newer versions, it’s intended to force the use of good practises.  Some of the things that are considered bad practise, and will result in an error if “use strict” is in use, are…

  • use of a variable not declared with the *var* keyword (e.g. var myVariable;), will result in an error.  Since all variables created without a “var” declaration are instantly turned into globals, causing potentially undesired side affects, this is a good thing.  If not using strict mode, declaration of variables without the “var” keyword is not recommended.
  • attempting to write to non-writable properties, a getter only property, a non-existent property, a non-existent object, or a non-existent variable, will throw an error (1)
  • duplicating parameter names in a function (1)
  • use of variable names that are common language keywords are not allowed. Examples are “arguments”, “eval”, etc (1)
  • The “this” keyword is no longer available to global functions; i.e. those functions that are not members of an object. (1)

Patterns

Array Length Caching

// Caching array length is between 2 and 190 times faster, depending on the browser
var myArray = [0,2,4,6,8];
for (var i = 0, max = myArray.length; i < max; i++) { } // ref: (3) p.g. 16

Configuration Objects

It’s a good practise to use configuration objects for passing parameters. Some of the reasons to use them are…

  • They prevent changing of the API, when you add or remove parameters, there by making API modifications easier.
  • The order of parameters no longer matter.
  • You can skip optional parameters without worrying about putting those at the end of the parameter list.
function doSomething(options) {  console.log(options) };

doSomething({ name: 'Trent', gender: 'male', occupation: 'full time nerd'});

Furthermore, jQuery has functionality to allow merging of what is passed into a function with default values. The default values are overwritten if present in the parameter object, and a new object is returned.

Functions

Lexical Scope

JavaScript functions use lexical scoping (known as closures).  This means that variables in the immediate parent code are available to the code within the closure, and in fact are the variable that is used regardless of the scope of the call.

var myGlobal = "global";
function myFunction()
{
  var myVariable = "local";
  function f() { return myVariable;}
}
myFunction() // returns "local".

Objects

Functions themselves are objects.  This functionality allows for turning a function into a constructor, which sets up an object instance.  It also allows for requesting the function’s name via it’s toString() method.

They also have their own *this* keyword, which refers to the object they are contained within, or the global object if they are not a member of another object.  With ECMAScript 5, and the strict mode enabled, the *this* keyword is undefined when the function is not part of an object.

Language Quirks

Javascript can be quite quirky at times.  And if you’re not aware of some of the issues, it’s rather annoying to figure out what’s happening.

Expressions

Some interesting expressions that are fairly important to know.

var myArray = myArray || []; // checks for undefined, then assigns an empty array
var myVar = 2; var myVar2 = "2";
myVar == myVar2; // true
myVar === myVar2; // false - operator strictly checks for equality without type conversions.
false == 0; // true - use === instead
"" == 0; // true - use === instead
[0,1,2] == "0,1,2"; // true - use === instead

Hoisting

Variable hoisting and function hoisting occur in JavaScript.  This means that it doesn’t matter where you define the variable or function, within the scope that you’re using it in, it is always available immediately.  In the case of variables, the assignment is not available until the location that it occurs, but the variable reference is. Named functions are available to be used immediately, no matter where they occur in the scope.

Due to hoisting nature, there are some gotchas with function expressions assigned to variables.  A function expressions assigned to a variable, will have the variable hoisted, but not the function.  So, the “typeof” the function variable is essentially undefined.  An actual *named* function on the other hand is hoisted to the top, along with it’s declaration, making it immediately available for use. (3) p.g 61

console.log(typeof a); // undefined and unusable as a function
console.log(typeof b); // function

var a = function() { console.log('hello a'); }
function b() { console.log('hello b'); }

Local Scope

It’s important to note that local scope cannot be created just by blocks.  e.g. { var myVar; } doesn’t make myVar local if it’s defined in the parent scope.  You have to create a function, or a function expression (otherwise known as a closure). (3) p.g. 58

Functions

If you have an object with a function, and you pass that function by reference to another function, when it is called the *this* keyword will not reference the parent object.  It will instead reference the global object, or will be undefined if “use strict” is in use.  An example snippet is below.

var myObject = {
  doSomething: function () 
  {
    console.log(this); // global object or undefined in call below; NOT myObject
  }
}

function doThis(callback) { callback(); }

// should result in displaying the window object, if pasted 
// into a javascript browser console.
doThis(myObject.doSomething);  

Sources:

(1)  W3C Schools

(2) Java Script Pocket Reference (3rd Edition) by David Flanagan

(3) Java Script Patterns by Stoyan Stefanov

]]>
http://blog.adamsbros.org/2014/11/27/java-script-quick-start-tips-and-best-practises/feed/ 0
Eclipse Android Hello World Tutorial Video – Part 3 http://blog.adamsbros.org/2011/07/22/eclipse-android-hello-world-tutorial-video-%e2%80%93-part-3/ http://blog.adamsbros.org/2011/07/22/eclipse-android-hello-world-tutorial-video-%e2%80%93-part-3/#comments Sat, 23 Jul 2011 03:01:11 +0000 http://blog.adamsbros.org/?p=394 In third part of the android hello world video, we explain the different components of the application, and why things are done in a certain way.  This video is a bit raw.  However, rather than editing the videos, I’m going to try and improve my presentation skills as I go.

Before we get started, the code for part 3 is located on github under the tag “part3“.  You should be able to switch to that tag and download a tar.gz of the code.   Or you can simply clone it as follows.

git clone git://github.com/TrentonAdams/HelloAndroid.git HelloAndroid
cd HelloAndroid
git checkout part3

In this video, we will

  1. explain the various sections of code
  2. explain the semantics of the android R class for referencing resources
  3. explain the use of localized resource files

We have one new screenshot from this video in the series.  It is the French version of the application.

If this video fails to play, please check back later, it may still be processing.

]]>
http://blog.adamsbros.org/2011/07/22/eclipse-android-hello-world-tutorial-video-%e2%80%93-part-3/feed/ 1
Eclipse Android Hello World Tutorial Video – Part 2 http://blog.adamsbros.org/2011/07/16/eclipse-android-hello-world-tutorial-video-%e2%80%93-part-2/ http://blog.adamsbros.org/2011/07/16/eclipse-android-hello-world-tutorial-video-%e2%80%93-part-2/#comments Sun, 17 Jul 2011 01:05:37 +0000 http://blog.adamsbros.org/?p=368 Part 3 – Code Explained

Okay, I’ve finished another android development demo video.  Sorry it took so long, I got really busy with a new computer and what not, and life in general.  In the next video in this series, I will explain the details of the hello android application.  So, if you do not understand some of what is happening, stay tuned for the next video in the series.

Before we get started, the code for part 2 is located on github under the tag “part2“.  You should be able to switch to that tag and download a tar.gz of the code.   Or you can simply clone it as follows.

git clone git://github.com/TrentonAdams/HelloAndroid.git HelloAndroid
cd HelloAndroid
git checkout part2

In this video, we do the following…

  1. an actual android application with a button that opens a dialog box. The dialog box has a Okay/Cancel button.
  2. Handling and implementing events
    1. onCreateDialog(int) – when a dialog is requested to be created in this activity, this method is called
    2. onClick(View arg0) – we tied the click event from the button to our activity rather than making a custom class for it
  3. log debug information to the android log
  4. use logcat to see the debug information

Below are the two screens that you will see in this application.

Hello Android Screenshot
Hello Android Okay/Cancel Dialog


This android demo was created using a software package under Linux called “recordMyDesktop”.  It’s terribly slow for encoding the video, which it does after the video has been recorded.  I think it’s recording my whole screen as a series of screenshots, which is probably what takes it so long.  I used it from the command line, as I have not yet attempted to use a GUI tool with it.  I found that I basically required 240 fps, because it did not capture all of my selections if I did not use a high frame rate.  This time I decreased the quality and the bitrate, as it did not seem to make a huge impact on quality.

recordmydesktop –pause-shortcut Control+Shift+P –fps 240 –v_quality 30 –v_bitrate 400 -o ~/Videos/newvideo

This is based in part on the Android Hello World documentation at http://developer.android.com/resources/tutorials/hello-world.html

]]>
http://blog.adamsbros.org/2011/07/16/eclipse-android-hello-world-tutorial-video-%e2%80%93-part-2/feed/ 1
Eclipse Android Hello World Tutorial Video – Part 1 http://blog.adamsbros.org/2011/07/07/eclipse-android-hello-world-tutorial-video-part-1/ http://blog.adamsbros.org/2011/07/07/eclipse-android-hello-world-tutorial-video-part-1/#respond Thu, 07 Jul 2011 06:22:25 +0000 http://blog.adamsbros.org/?p=341 Part 2

My intention is to make all of my android videos as simple as possible, and as short as possible. That way you can learn what you need to, and get on with it.

This is a quick demo on how to get started on developing for Android.  It is “hopefully” the first in a serious of android demo videos that I will be creating.  I am mainly creating them for myself, so as to become familiar with basic android development tasks, and also to play with recording sessions; I too am a newbie to Android development.  I am putting them on YouTube in case anyone else may find them valuable; perhaps for their simplicity.  I hope you enjoy.

This android demo was created using a software package under Linux called “recordMyDesktop”.  I used it from the command line, as I have not yet attempted to use a GUI tool with it.  I found that I basically required 60 fps, because it did not capture all of my selections if I did not use a high frame rate.

recordmydesktop –fps 60 –v_bitrate 3500 -o helloandroid.ogv

This is based in part on the Android Hello World documentation at http://developer.android.com/resources/tutorials/hello-world.html

]]>
http://blog.adamsbros.org/2011/07/07/eclipse-android-hello-world-tutorial-video-part-1/feed/ 0
Java LDAP Persistence API http://blog.adamsbros.org/2011/01/01/ldap-persistence-api/ http://blog.adamsbros.org/2011/01/01/ldap-persistence-api/#comments Sat, 01 Jan 2011 22:20:01 +0000 http://blog.adamsbros.org/?p=302 I’ve started a project called LDAP Persistence API for Java, or LPA for short. It is a Java framework for interacting with LDAP entries using pure Java objects. It is based on Java annotations.

It is no were near to being complete, but the query functionality is working. I still have a lot of work to do, in order to make it be able to persist existing annotated Java objects to LDAP.  I’m likely to create some sort of intermediate step, until I can finish that.

A quick example of how easy it is to use, pulled directly from one of our Classes and unit tests. The following class, is a portion of our LdapOrganization Class, showing how simple it is to annotate the class to be automatically loaded from LDAP.

/**
 * This file is part of the Ldap Persistence API (LPA).
 *
 * Copyright Trenton D. Adams
 *
 * LPA is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * LPA is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with LPA.  If not, see .
 *
 * See the COPYING file for more information.
 */
package ca.tnt.ldaputils.impl;

import ca.tnt.ldaputils.ILdapGroup;
import ca.tnt.ldaputils.ILdapOrganization;
import ca.tnt.ldaputils.annotations.LdapAttribute;
import ca.tnt.ldaputils.annotations.LdapEntity;
import ca.tnt.ldaputils.annotations.TypeHandler;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.log4j.Logger;

import java.util.*;

/**
 * Implements an LDAP organization object.
 *
 * Created :  16-Apr-2006 10:25:36 PM MST
 *
 * Modified : $Date$ UTC
 *
 * Revision : $Revision$
 *
 *
 * @author Trenton D. Adams
 */
@LdapEntity(requiredObjectClasses = {"organization"})
public class LdapOrganization extends LdapEntry
    implements ILdapOrganization, Comparable, TypeHandler
{
    private static final Logger logger = Logger.getLogger(
        LdapOrganization.class);

    @LdapAttribute(name = "businessCategory", aggregateClass = LdapGroup.class,
        referencedDNMethod = "getCategoryDN"
        /*"cn=?,ou=bus-categories,dc=example,dc=com"*/
    )
    private SortedMap businessCategories;

    @LdapAttribute(name = "telephoneNumber")
    private String telephoneNumber;
    @LdapAttribute(name = "facsimileTelephoneNumber")
    private String facsimileTelephoneNumber;
    @LdapAttribute(name = "street")
    private String street;
    @LdapAttribute(name = "postOfficeBox")
    private String postOfficeBox;
    @LdapAttribute(name = "postalAddress")
    private String postalAddress;
    @LdapAttribute(name = "postalCode")
    private String postalCode;
    @LdapAttribute(name = "l")
    private String locality;
    @LdapAttribute(name = "o")
    private String organization;

    // ... getters, setters, etc.
}

The following is a unit test, testing the above class. Take special note of how it is a single method call, to retrieve your entry, simply by calling manager.find(Class theClass, ldapName).

        private LdapManager manager;

        manager = new LdapManager("localhost", "",
            "uid=admin,ou=system", "secret");

        final LdapName ldapName = new LdapName(
            "o=Pulp Mill.,ou=businesses,dc=example,dc=com");
        final LdapOrganization ldapEntry = (LdapOrganization) manager.find(
            LdapOrganization.class, ldapName);
        final SortedMap categories =
            ldapEntry.getBusinessCategories();
        Assert.assertNotNull("Manufacturing category does not exist",
            categories.get("Manufacturing"));
        Assert.assertNotNull("Pulp & Paper Products category does not exist",
            categories.get("Pulp & Paper Products"));
        Assert.assertEquals("Pulp Mill business categories", 2,
            categories.size());
        Assert.assertEquals("Organization should be Pulp Mill",
            "Pulp Mill.", ldapEntry.getOrganization());

We have a good start on the project, but we have a very long way to go. If anyone is interested in helping out with the framework, please wander over to github, and check it out.

]]>
http://blog.adamsbros.org/2011/01/01/ldap-persistence-api/feed/ 2
Java Array Reflection http://blog.adamsbros.org/2010/12/08/java-array-reflection/ http://blog.adamsbros.org/2010/12/08/java-array-reflection/#comments Thu, 09 Dec 2010 03:32:43 +0000 http://blog.adamsbros.org/?p=292 In this article we talk about reflection with arrays in Java. Java array reflection is not difficult, but it can be trying to figure it out without a good example. Ultimately, what I needed was a way of injecting information into an array field. Of course, you need to inject the same “type” of array as the field is. That is what can be difficult to figure out, if you’ve never done it before.

In this example, I am using Java 1.6. I won’t bother determining what is, or is not supported in prior versions of the Java language.


I may at some point create a “working” example, rather than a code snippet. But, if you’ve done reflection before, you should get the gist of what I’m doing here.

Basically, all we do is

  1. create a java.util.List object
  2. create a new array of the same type as the field we’re reflecting
  3. ask the List object to insert all it’s elements into the new array
  4. assign the array to the field.
            final Class refType = field.getType();
            if (refType.isArray())
            {   // handle multiple ldap values
                final NamingEnumeration values = attribute.getAll();

                final List ldapEntities = new ArrayList();
                while (values.hasMore())
                {   // iterate through all ldap attributes
                    final Object valueObject = values.next();
                    ldapEntities.add(getReferencedDN(agg.aggregateClass(),
                        dnReference, valueObject));
                }
                // convert to the array type used in the field
                // create an array the same size as the ldapEntities List
                final Object refArray = Array.newInstance(
                    refType.getComponentType(), ldapEntities.size());
                // ask List implementation to copy all elements to the new array
                final Object aggregatedList = ldapEntities.toArray(
                    (Object[]) refArray);
                field.setAccessible(true);
                field.set(object, aggregatedList);
                field.setAccessible(false);
            }

]]>
							http://blog.adamsbros.org/2010/12/08/java-array-reflection/feed/
		2
							
		
		What is JAXB and JAXB Example Code
		http://blog.adamsbros.org/2010/02/07/jaxb-example-code/
				http://blog.adamsbros.org/2010/02/07/jaxb-example-code/#comments
				Mon, 08 Feb 2010 03:12:28 +0000
		
				
		
		

		http://blog.adamsbros.org/?p=200
				
								I thought it may be nice for those googlers that want to know about JAXB, to have a quick working example to use.  So, that is the purpose of this post.

First off, what is JAXB?  Well, simply put, JAXB is for converting Java objects to XML or from XML to Java objects.  With the advent of Java 1.5, and annotations, this becomes extremely simple.

Download JAXB, dependencies to your local computer, and put them in a folder called “libs”. The dependencies JARs I have are…

  • activation-1.1.jar
  • jaxb-api-2.0.jar
  • jaxb-impl-2.0.5.jar
  • jsr173_api-1.0.jar

Copy the following Java source code to Employee.java, and proceed with the instructions below

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.*;
import java.io.StringReader;
import java.io.StringWriter;

@XmlRootElement(name = "employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee
{
    public static void main(String args[]) throws JAXBException
    {
        final Employee john = new Employee();
        john.setId(1);
        john.setFirstName("John");
        john.setMiddleName("Robert");
        john.setLastName("Doe");

        // write it out as XML
        final JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
        StringWriter writer = new StringWriter();
        jaxbContext.createMarshaller().marshal(john, writer);

        // read it from XML
        final Employee johnRead =
            (Employee) jaxbContext.createUnmarshaller().unmarshal(
                new StringReader(writer.toString()));
        if (john.equals(johnRead))
        {   // write the new object out as XML again.
            writer = new StringWriter();
            jaxbContext.createMarshaller().marshal(johnRead, writer);
            System.out.println(
                "johnRead was identical to john: \n" + writer.toString());
        }
        else
        {
            System.out.println("john and johnRead are not equal");
        }
    }

    @XmlAttribute
    private int id;

    /**
     * Employee's first name
     */
    @XmlElement
    private
    String firstName;

    /**
     * Employee's middle name
     */
    @XmlElement
    private
    String middleName;

    /**
     * Employee's last name
     */
    @XmlElement
    private
    String lastName;

    public Employee()
    {
    }

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    public String getLastName()
    {
        return lastName;
    }

    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }

    public String getMiddleName()
    {
        return middleName;
    }

    public void setMiddleName(String middleName)
    {
        this.middleName = middleName;
    }

    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Employee employee = (Employee) o;

        if (id != employee.id) return false;
        if (firstName != null ? !firstName.equals(employee.firstName) :
            employee.firstName != null) return false;
        if (lastName != null ? !lastName.equals(employee.lastName) :
            employee.lastName != null) return false;
        if (middleName != null ? !middleName.equals(employee.middleName) :
            employee.middleName != null) return false;

        return true;
    }

    @Override
    public int hashCode()
    {
        int result = id;
        result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
        result = 31 * result + (middleName != null ? middleName.hashCode() : 0);
        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
        return result;
    }

    @Override
    public String toString()
    {
        return "Employee{" +
            "id=" + id +
            ", firstName='" + firstName + '\'' +
            ", middleName='" + middleName + '\'' +
            ", lastName='" + lastName + '\'' +
            '}';
    }
}

The following commands will compile and run the source, if under a unix OS. If in windows, you’ll need to form your own classpath.

javac -classpath .:$(for jar in libs/*.jar; do echo -n "$jar:"; done) Employee.java
java -classpath .:$(for jar in libs/*.jar; do echo -n "$jar:"; done) Employee

The output should be as follows, but the XML will be on a single line…

johnRead was identical to john:


 John
 Robert
 Doe
]]>
http://blog.adamsbros.org/2010/02/07/jaxb-example-code/feed/ 42
ZK AJAX Status Bar http://blog.adamsbros.org/2010/01/31/zk-ajax-status-bar/ http://blog.adamsbros.org/2010/01/31/zk-ajax-status-bar/#comments Sun, 31 Jan 2010 08:45:43 +0000 http://blog.adamsbros.org/?p=172 Seeing that my research project is a mini accounting system, I thought it necessary to be able to display items in a status bar, like a real application.  It is very slightly unfortunate that ZK doesn’t have something integrated right in for this purpose.  But, given the versatility of ZK, it’s easy enough to resolve.

Features

I thought it important to have some useful features that make sense for what I’ve seen in status bars.

  • a method to set the status, with a delay before the status bar is cleared
  • a method to simply set the status, and leave it as is.  It would be up to the developer to clear the status later, if need be.  Or, the next status item would take over.
  • a very simple interface abstraction in case we want to change the type of component we use later, or something of that nature.  This will help us prevent the need to refactor a lot of code that could be using the status bar; we would only need to refactor the implementing class of the interface, leaving all of the code accessing the status bar entirely intact.

Future features might include…

  • methods for setting the status with color text
  • methods for setting the status with html
  • any other suggestions are welcome.

Window Width Status Bar

We first, of course, need to setup the actual status bar.  So, right before the end of the window, we do just that, with a “textbox”.  Now, there’s no reason you can’t use some other type of control, if it makes sense to.


The text box is implemented by a custom class, which we’ll delve into in a moment.  We also have a ZK timer, for implementing the automatic clearing feature, because it is illegal to access ZK elements from outside of a ZK event.  i.e. You cannot write your own thread to do it at a later time, as ZK will throw an IllegalStateException.

The Code

Interface Abstraction

We’ve kept the interface very simple, just two methods.  For more information, read the javadoc comments.

  • setStatus(String) allows setting of the status bar permanently
  • setStatus(String, int) allows setting of the status bar, and automatic clearing of it after a specified delay
package com.example.system;

/**
 * Handles setting of status bar messages.  All calls to this object must be
 * done from within the ZK framework, such as inside an event.
 *
 * Hides the details of what component is actually a status bar.  It could be a
 * textbox, or something else, but we don't want to be dependant on any specific
 * type of control, in case it changes in the future.
 *
 * Created :  Jan 31, 2010 1:39:37 AM MST
 *
 * Modified : $Date$ UTC
 *
 * Revision : $Revision$
 *
 * @author Trenton D. Adams
 */
public interface IStatusBar
{
    /**
     * Sets the status bar text for the time period indicated.
     *
     * @param statusText status text
     * @param timePeriod delay in seconds, before the status bar will be
     *                   cleared.
     */
    public void setStatus(final String statusText, final int timePeriod);

    /**
     * Sets the status bar text.  Pass null to clear.
     *
     * @param statusText status text or null to clear
     */
    public void setStatus(final String statusText);

    /**
     * @return the status text of the status bar.
     */
    public String getStatus();
}

Implementation

Essentially, all we are doing with the implement is as follows

  • implement AfterCompose, so we can setup a session variable to access the status bar from any ZK code, without much trouble
  • implement the setStatus() methods as described in the feature section.  One takes an extra argument for a delay, indicating how long before the status bar should be cleared.
package com.example.system;

import org.apache.log4j.Logger;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Timer;

/**
 * StatusBar handles setting the status bar text, and clearing it after a given
 * timeout.  Implements IStatusBar, to hide the details of what a status bar is
 * from the client code.  We use a textbox, but we could change that, who knows.
 *
 * Created :  Jan 31, 2010 12:42:29 AM MST
 *
 * Modified : $Date$ UTC
 *
 * Revision : $Revision$
 *
 * @author Trenton D. Adams
 */
public class StatusBar extends Textbox implements AfterCompose, IStatusBar
{
    @SuppressWarnings({"ConstantNamingConvention"})
    private static final Logger logger = Logger.getLogger(StatusBar.class);

    public StatusBar()
    {
    }

    public void afterCompose()
    {
        logger.info("status bar running as " + getId());
        // TODO find a better method, getFellow() didn't work
        final Session session = getDesktop().getSession();
        session.setAttribute("status", this);
    }

    public void setStatus(final String statusText, final int timePeriod)
    {
        setStatus(statusText);
        // the timer must be in the page, or the page is inactive and this
        // call would never happen?
        final Timer timer = (Timer) getFellow("statusTimer");
        timer.setDelay(timePeriod * 1000);
        timer.start();
    }

    public void setStatus(final String statusText)
    {
        setText(statusText);
    }

    public String getStatus()
    {
        return getText();
    }
}

Using the Status Bar

The following code must be used inside of a ZK event handler, such as one that comes from the click of a button, or a mouse over event, etc.  Basically, all we’re doing is grabbing the status bar object from the session, and request the status be set.  That’s all there is to it.

final Session session = getDesktop().getSession();
final IStatusBar statusBar = (IStatusBar) session.getAttribute("status");
statusBar.setStatus("Transaction Posted", 5);

Results

I’m attaching a screen shot of the results of my status bar.

ZK Status bar

]]>
http://blog.adamsbros.org/2010/01/31/zk-ajax-status-bar/feed/ 3