Kiosk Applications

Kiosk applications and other self-service systems are rapidly growing business area.  Internet connectivity, a greater variety of interface equipment and prices that continue to drop are enabling the cost-effective deployment of an ever widening array of applications. Hardware is available for a wide spectrum of requirements. Vendors such as NCR and 5point can meet most any need

Kiosk Software application development is relatively straightforward. Many kiosk applications now use an ordinary PC attached to various more specialized interface equipment such as touchscreens, card readers, special keyboards, and trackballs. Equipment and kiosks can be purchased for either indoor or outdoor usage, outdoor equipment is noticably more expensive.  Outdoor kiosks have special needs due to weather, water and sunlight.  

Usually either .NET or Java is used as an application language. The operating system is either Linux or Windows XP. Kiosk applications can be a specialized web site program or more traditional client application.  There are special security programs for controlling access and monitoring the kiosks (such as Kioware). These programs prevent access to the computer or any application other than those specifically permitted.

Touchscreen applications are much like any other except the interface elements typically have to be much larger. This can be especially challenging when working with spreadsheet like programs or interfaces. Most interface hardware available today has a well defined software API and can usually interact seamlessly with the programming.

Unidev recently completed two separate kiosk applications. One was an application which allowed visitors to search a large database of products and images to obtain detailed information about the products and pricing. By automatically providing this information on a round the clock basis, the vendor is able to interact with all potential customers even when salespeople are not available.

 The other application provides an automated method for filling out and validating data entry forms by customers. This application saves a considerable amount of labor as well as ensures the data is correctly filled out and validated while the customer is on site saving considerable rework.

Both of these applications communicate with a central server for obtaining updates of both code and data, sending report information to the server and monitoring. The server applications provide a central data collection point for management reports.

Self-service kiosks have proven themselves to be a cost effective tool for both labor savings and improving service levels to customers.

2007 Company Highlights

2007 saw continued growth and expansion of the web marketing and web design service lines of The Net Impact business unit.  The web development team went through a number of process changes over the year as staff was added. A new formal development methodology was implemented in conjunction with a new enterprise project management system. These changes allowed for much improved communications with customers and with other teams in the company. The Net Impact formed several strategic partnerships in the 4th quarter that will both expand the potential client base as well as significantly increase the sales efforts for the services.

The software development and outsourcing groups had the strongest growth for the Unidev business unit. Outsourcing development, production support and maintenance continues to be a strong and growing revenue contributor. The software development team primarily used .NET and J2EE this last year.  We saw very little demand for other technologies. An important goal for 2007 was to improve development methodologies and processes in order to deploy products more rapidly. The software group implemented a much improved enterprise project management system tool as well as organizational and process changes to successfully meet this goal.  

2007 was a year of significant growth and change within the company as The Net Impact became a fully integrated business unit. 2008 should be a great year as we continue to build and improve on 2007. For 2008 we will be working to increase our commercial applications integration services, developing new and improved technology solutions to web marketing and increasing our mobile applications development efforts.

Java Calendar and Date Operations

Java – Find a given date belongs in which quarter:
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern(“MM/dd/yyyy”);
Calendar calendar = Calendar.getInstance();
Date processDate = sdf.parse(“4/10/2007″);
calendar.setTime(processDate);
Date date1 = calendar.getTime();
int quarter = TestDate.getQuarter(date1);
System.out.println(“Quarter for the date : “+sdf.format(calendar.getTime())+” is : “+quarter);
Prints the following Result :
Quarter for the date : 04/10/2007 is : 2

Java – Code for getQuarter() function:
public static int getQuarter(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int[] months = { 3, 6, 9, 12 };
int count = 0;
do {
calendar.set(year, months[count++], 1);
Date tempDt = calendar.getTime();
if(date.compareTo(tempDt)
return count;
} while(count
return 0;
}

Java – Find previous quarter begin and end dates for a given date:
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern(“MM/dd/yyyy”);
Calendar calendar = Calendar.getInstance();
Date processDate = sdf.parse(“4/10/2007″);
calendar.setTime(processDate);
Date date1 = calendar.getTime();
int quarter = TestDate.getQuarter(date1);
String currentQuarterBeginDate = “”;
String fromDt=”";
String toDt=”";
if ( quarter ==1){
currentQuarterBeginDate = “01/01/”+calendar.get(Calendar.YEAR);
}
if ( quarter ==2){
currentQuarterBeginDate = “04/01/”+calendar.get(Calendar.YEAR);
}
if ( quarter ==3){
currentQuarterBeginDate = “07/01/”+calendar.get(Calendar.YEAR);
}
if ( quarter ==4){
currentQuarterBeginDate = “10/01/”+calendar.get(Calendar.YEAR);
}
calendar.setTime(sdf.parse(currentQuarterBeginDate));
calendar.add(Calendar.MONTH, 3*-1);
fromDt = sdf.format(calendar.getTime());
String formmatedQuarterBeginDate = sdf.format(calendar.getTime());
calendar.setTime(new java.util.Date(formmatedQuarterBeginDate));
calendar.add(Calendar.MONTH, 3);
calendar.add(Calendar.DAY_OF_MONTH, -1);
toDt = sdf.format(calendar.getTime());
System.out.println(“Previous Quarter Begin Date : “+fromDt);
System.out.println(“Previous Quarter End Date : “+toDt);

Prints the following Result :
Previous Quarter Begin Date : 01/01/2007
Previous Quarter End Date : 03/31/2007

Java – Find previous Date for a given date:
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern(“MM/dd/yyyy”);
Calendar calendar = Calendar.getInstance();
Date processDate = sdf.parse(“4/10/2007″);
calendar.setTime(processDate);
calendar.add(Calendar.DAY_OF_MONTH, -1);
String previousDate = sdf.format(calendar.getTime());
System.out.println(“Previous Date is :”+previousDate);
Prints the following Result :
Previous Date is :04/09/2007

Java – Find previous Sunday for a given date:
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern(“MM/dd/yyyy”);
Calendar calendar = Calendar.getInstance();
Date processDate = sdf.parse(“4/24/2007″);
calendar.setTime(processDate);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
calendar.add(Calendar.DAY_OF_MONTH,-1*(dayOfWeek-1));
calendar.setTime(calendar.getTime());
String endDt = sdf.format(calendar.getTime());
System.out.println(“Previous Sunday is :”+endDt);
Prints the following Result :
Previous Sunday is :04/22/2007

Enjoy!!!!

Improve ASP.NET Performance and Scalability

Do you have performance issue on your ASP.NET website? Do you want to boost your site’s scalability? Do you know the bottleneck of your site? Do you want your site performs well under 100 times more traffic? Here are some good posts about this:

10 ASP.NET Performance and Scalability Secrets

Boost ASP.NET performance with deferred content loading

Unidev training never ends…..

Keeping a medium sized contract programming company up to speed on the latest technologies is a daily challenge. With a wide variety of technologies and skillsets in use at any given time and with the future technology needs of the company being very customer driven, it can be very difficult to put together individualized training plans. Our solution was to develop a more ‘university’ environment where we constantly have optional classes on a wide variety of new and current technologies. In this way, employees are able to choose which directions they feel works best for them and they are able to investigate a variety of choices without having to commit to a particular path. In our experience, this has worked quite well with a number of surprises about which directions people choose. With an array of topics such as J2EE, C# .NET, Web Marketing methods, HTML, Project Management, RAD and Network Architecture, employees can explore many possibilities. Unidev has a number of types of work including software developers who work on customer projects at the development center, technology consultants who work both at the customer site and in-house, Web marketing consultants and IT staffing personnel who augment customer development teams. This variety of work along with the various technologies employed makes for a very interesting learning environment.

Using UTF-8 in Ajax, PHP, MySQL & ASP.NET

We have a project which needs to show foreign language, like Chinese, on a web page. And we are using RICO 2.0, PHP, MySQL & ASP.NET in the project. To achieve this, we decide to use UTF-8 character set and the following changes need to be done:

  • MySQL:

To store UTF-8 in a table field, you need to set column’s charset => utf8 and collate => utf8_unicode_ci

  • Web Page:

To show foreign language in a web page, the page file has to be saved as encoding UTF-8

  • PHP:

The default encoding for PHP 5 is UTF-8, so it supports foreign language. But if you use PHP to retrieve UTF-8 characters from MySQL, you must add mysql_query(‘SET NAMES utf8′); after connecting to MySQL database for setting up the connection encoding.

  • RICO:

As for RICO Live gird, Ajax response must start with <?xml version=”1.0″ encoding=”utf-8″?>

  • ASP.NET:

First make sure you have following line in you web.config
<globalization requestEncoding=”utf-8″ responseEncoding=”utf-8″ fileEncoding=”utf-8″/>
Second, keep both .aspx and code behind file save as the same encoding UTF-8
If you need to access the UTF-8 characters in MySQL database, be sure to use MySQL Connector/Net 5.0 or up with undocumented setting: charset=utf8 in connection string. We tried ODBC driver for MySQL, it doesn’t work properly with UTF-8.

Java and swap for HPUX systems

We recently pushed a couple of new Java programs to our client’s application server (HPUX) and soon thereafter they started to receive alerts about the swap running out of space. Of course, being the “new kid on the block” our programs were suspect. While these programs were not the only ones taking up a good deal of swap space, we were a bit perplexed why they were taking much at all.

These programs were fairly small in terms of functionality, but the amount of swap space it was using was around 600-700MB. Here is a summary of our findings (note that some of these details might be different on a Windows system due to differences in memory management):

  • A common theme is that most java processes have a big difference between the residual memory and the total virtual memory.
  • Java will allocate at a minimum about 200 MB of swap even for the simplest of programs. We tested using a simple program on both a HPUX and a linux server. The best and only documentation I could find about this was at the URL below. The bottom line is that this is probably the behavior of the JVM and out of our control so we just have to deal with it.

    http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/778089cbe0c9814c/5b0dfcea715d9055?lnk=st&q=java+uses+virtual+memory&rnum=20&hl=en#5b0dfcea715d9055It

    It is reserving space for example for threads that you may or may not create. It is awkward to rearrange memory on the fly, so the JVM parcels out the virtual ram for various tables when it first loads.

  • The -Xms and -Xmx parameters do affect the java heap but it does not control the total memory footprint. It is only a piece of the total size.
  • -Xmx alone can affect the total virtual memory size. Currently the processes have -Xms24m and -Xmx512m. Immediately after starting these programs, we saw the swap allocation jump to 600-700MB. When we changed -Xmx to 24m, it dropped to a little over 200MB.
  • In relation to the above, the normal behavior of the garbage collector is to garbage collect only when it needs to free up memory. Having a too high of a -Xmx value could mean that it will never garbage collect, which means it won’t reuse memory. We see this in the Weblogic environment too but in that environment all of the memory usually gets used at some point.
  • There is a new tool built into Java 5 and up called jmap that will give you heap information about a java process. This tool would make tuning the heap parms really simple. Unfortunately the process also has to be running using Java 5 so we cannot use it at this time. There is a version for 1.4 but it only works on Solaris.

Spring AbstractEnterpriseBean and a memory leak

One of our applications was determined to be leaking memory. The leak was traced back to some stateful EJB’s that were extending Spring’s AbstractStatefulSession bean class. While I could not trace to the exact source of the leak, it seems to be related to the unloading of the BeanFactory.

As per the documentation, Spring’s default behavior will initialize a new ApplicationContext when the EJB object is created. It also states that the BeanFactory (which is the ApplicationContext) is unloaded when the EJB is removed.

One of the first things I checked was ensuring the EJB’s were in fact being removed. They were. At some point I remembered that in a more recent project, we changed the beanFactoryLocator to the ContextSingletonBeanFactoryLocator so that all EJBs use the same context (it also happens we setup the web application to use the same context too). The newer application did not have the memory leak so I decided to implement it here. I also figured that even if it didn’t fix the leak, this method is more efficient since there is no reason to have the context loaded everytime. To implement, I just overloaded the setSessionContext method:

SessionContext code

Once implemented the leak went away. I never took the time to dig in and see what the true offender was, but it was found that some of the hibernate SingleTableEntityPersister objects were still present after leak. This could mean that it is Spring not properly cleaning things up or Hibernate itself has the leak.

As info this method was already implemented with our stateless EJB’s, so I could not confirm if the issue existed for AbstractStatelessSessionBean.  However since both abstract classes use the unloadBeanFactory method from AbstractSessionBean, I would figure the issue would present itself — although due to Weblogic pooling the stateless EJB’s, it is probably not as noticable.

Specifics:

  • Weblogic 8.1 sp4
  • JRockit 1.4.2_13
  • Spring 1.2.9
  • Hibernate 3.2.5

Development doesn’t have to be all work

We’ve had the opportunity to work with a lot of new technologies lately. Sometimes with friendly customer sites ;> but mostly within our own sites. Unidev strongly encourages and supports everyone within the company experimenting with new technologies as they come around. We do this by teaching internal classes, providing test web sites, providing a variety of real live high volume web sites for production testing as well as having a test lab with different operating systems, languages and browsers, Linux and Windows servers and pretty much any commercial software you could imagine.

The results of this policy are manyfold. The primary benefit of this goes to our customers as it ensures that we are using the very best available methods and tools for developing their software and websites. Recently a large customer with SQL Server and DB2 databases needed several dynamic data driven web pages quickly. We were able to deploy an Ajax tool we had created as an experiment for one of our internal web sites that worked very well and we were able to get the site developed very quickly.

Today we are continuing to experiment in the Windows .Net, Java/J2EE and Linux PHP areas. We continue working with new Ajax tools as well as Ruby on Rails, Microsoft Silverlight and databases, BLOGS, social networking, Hibernate, XML data messaging, RSS feeds and RSS feed readers (used to display news on the unidev home page).

Good Stuff

Add Interactive Map to your website using Google Maps API

Interactive maps has become an inevitable part of modern web applications and introduction of Google Map API has made it even easier to integrate an interactive map to your website. Areas on which interactive maps have proved itself are tourism related websites and service oriented websites. In this blog we will see how we can add an interactive map to your website using Google Map API and AJAX to process the response from the server.

The first step in integrating a map in your website is to request  a Google map API key. You can request  a Google Maps API key here. If you have URL for your website, you need to specify the URL while requesting key. If you are playing around with the API, you can very well request for http://localhost. If you are using a port number , you need to specify the port number also. For example http://localhost:8080. Once you get the key you can use the key for all subfolders of http://localhost.

This is Source of an HTML page that displays map of 1415 Elbridge Payne Rd,Chesterfield,MO 63017. You need to know the latitude and longitude of the address to display map in your web page. If you don’t know the latitude and longitude , there are many online services that provide services to get latitude and longitude of an address . Another way of implementing this is to use geoCoder provided by Google Map API to get the latitude and longitude by providing an address. We will come to this in a while.

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
  “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd“>
<html xmlns=”http://www.w3.org/1999/xhtml“>
  <head>
    <meta http-equiv=”content-type” content=”text/html;
                                     charset=utf-8″/>
    <title>Google Maps JavaScript API Example</title>
    <script  src=”http://maps.google.com/maps?file=api&v=2&key=
         ABQIAAAAR7yXyXxWnmYNsvbV6JWv5hT2yXp_ZAY8_ufC3CFXhHIE1NvwkxTvGi-   GhomVbgkbC6tv2C8JocyNEg”
      type=”text/javascript”></script>
    <script type=”text/javascript”>
    //<![CDATA[
    function load() {
      if (GBrowserIsCompatible()) {
     var map = new GMap2(document.getElementById("map"));
     map.setCenter(new GLatLng(38.65, -90.56), 8);
     map.addControl(new GSmallMapControl());
     map.addControl(new GOverviewMapControl());
     var point = new GLatLng(38.65, -90.56);
     marker = new GMarker(point);
     map.addOverlay(marker)
     GEvent.addListener(marker, "click", function() {
     marker.openInfoWindowHtml("<p>Unidev: Custom Software and Applicaton Development</p>”});
  }

    }
    //]]>
    </script>
  </head>
  <body onload=”load()”>
    <div id=”map” style=”width: 800px; height: 600px”></div>
  </body>
</html>

Map of Unidev

Class GMap2 represents a map instance and you can create as many instances as you want. addcontrol() method can be used to add controls to your map.GSmallMapControl() enables Zoom functionality. Event handling is implemented using GEvent.addListener() method. GMarker class marks a point of interest in your map.OpenInfoWindowHtml() method opens an informational window on ‘OnClick’ event. Place holder for map in this example is a <div> tag with id ‘map’.
Adding an Interactive Map to your web application:
This example shows how to add a user driven map in your web application. First step in creating an interactive map is to have a form in your web page where users can enter the address and description of their point of interest.
Given below is the bean and DAO implementation class.
public class GMarker
{
    private Long id;
    private String address;
    private String description;
// Need to have setters , getters and a costructor that takes all the varaibales)
}

We have another Location object that stores data entered by users. We read data from the Location table(which is populated by the data submitted by users) and create Gmarker object. This DAO implementation is not Table  driven , we read hardcoded data from a Map. In realworld DAO Implmentation would be Table driven.

DAO implementation:
public class PickDAOImpl implements PickDAO
{
private static final Map myPicks = new HashMap();
    static {
    myPicks.put(“1″,new GMarker(new Long(1),”1415 Elbridge Payne  Rd,Chesterfield,MO,63017″,”Unidev: Custom Software and Application Development”));
    myPicks.put(“2″,new GMarker(new Long(2),”1400 Douglas Street,Omaha,NE”,”Union Pacific Railroad”));
    }
 public List findAllAsMarkers() {
        List results = new ArrayList();
        Collection allLocations = myPicks.values();
        Iterator locIt = allLocations.iterator();
        GMarker location = null;
        while(locIt.hasNext()){
            location = (GMarker)locIt.next();
            results.add(new GMarker(location.getId(),
                    location.getAddress(),
                    location.getDescription()));
        }
   return results;
    }
}

Heart of Ajax is XMLHttpRequest object and however in this example we are using Google’s version of XMLHttpRequest object, that is GXmlHttp class. Ajax makes the request to the servlet, which would be processed by the servlet  and Servlet returned XML Document object can be processed by Javascript DOM functions. We are using Xsteam implementation provided by http://xstream.codehaus.org/ to generate XML document from Java object. Other open source libraries like Apache and Castor can also be used to generate XML document from Java objects.

XML document generated by the servlet for the request to get all user submitted addresses in the database would look like this.
<list>
  <marker>
    <id>2</id>
    <address>1400 Douglas Street,Omaha,NE</address>
    <description>Union Pacific Railroad</description>
  </marker>
  <marker>
    <id>1</id>
    <address>1415 Elbridge Payne Rd,Chesterfield,MO,63017</address>
    <description>Unidev: Custom Software and Application Development</description>
  </marker>
</list>

Given below is the Servlet that generated the above XML document.

public class MyPickServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet
{
    private PickDAO pickDAO;
    public PickDAO getPickDAO()
    {
        if (pickDAO == null) {pickDAO = new PickDAOImpl();
        }
       return pickDAO;
    }

    public void setPickDAO(PickDAO pickDAO)
    {
        this.pickDAO = pickDAO;
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws  ServletException, IOException {
        String method=request.getParameter(“method”);
        XStream xstream = new XStream();
        xstream.alias(“marker”, GMarker.class);
        response.setContentType(“application/xml”);
 if (method.equals(“findAll”)) {
            List locations = getPickDAO().findAllAsMarkers();
            String xml = xstream.toXML(locations);
            response.getWriter().write(xml);
        }
}

The response generated by the Servlet is processed by javascript DOM functions. Given below is the HML page, that makes AJAX request to Server and process the response from the Server. The Javascript code has comments added to explain the important points.

<html>
 <head>
 <meta http-equiv=”content-type” content=”text/html; charset=utf-8″ />
  <title>Google Maps JavaScript API Example</title>
  <script
       src=”http://maps.google.com/maps?file=api&v=2&key=
                     ABQIAAAAR7yXyXxWnmYNsvbV6JWv5hT2yXp_ZAY8_ufC3CFXhHIE1NvwkxTvGi-GhomVbgkbC6tv2C8JocyNEg”
       type=”text/javascript”></script>
  <script type=”text/javascript”>
     var map = null;
         var gmarkers = [];
         var i =0;
         var address = null;
         var geocoder = null;
        var id = null;
      // method called on onLoad event
    function loadUserPicks() {
   map = new GMap2(document.getElementById(“map”));
         var request = GXmlHttp.create();
         request.open(“GET”, “myPick?method=findAll”, true);
         request.onreadystatechange = getCallbackFunction(request, processGmapData);
         request.send(null);
     }
    function getCallbackFunction(req, processData) {
          // Return an function that listens to the
          // XMLHttpRequest instance
              return function () {
         // If the request status is “complete”
           if (req.readyState == 4) {
             if (req.status == 200) {
                  // Got a response
                  // Pass the XML payload of the response to the
                  // handler function
          processData(req.responseXML);
 } else {
          // An HTTP problem has occurred
          alert(“HTTP error: “+req.status);
        }
      }
    }
  }
  var locMarkers = null;

function processGmapData(xmlDoc){
             // obtain the array of markers and loop through it
             locMarkers = xmlDoc.documentElement.getElementsByTagName(“marker”);
             displayPicks();
     }

    function displayPicks() {
      map.clearOverlays();
            for (var i = 0; i < locMarkers.length; i++) {
              // obtain the attribues of each marker
              var label = locMarkers[i].getElementsByTagName(“address”)[0].firstChild.nodeValue;
              address = label;
              map = new GMap2(document.getElementById(“map”));

            // Create new geocoding client object
          geocoder = new GClientGeocoder();

           // Retrieve location information for the address, pass it to addToMap()
           geocoder.getLocations(address, addToMap); }
     }
    function addToMap(response)
       {
            // Retrieve the object
           var place = response.Placemark[0];
           // Retrieve the latitude and longitude
           var point = new GLatLng(place.Point.coordinates[1],
             place.Point.coordinates[0]);
          // Center the map on this point
          map.setCenter(new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]),4);
          map.addControl(new GSmallMapControl());
          map.addControl(new GOverviewMapControl());
         var marker = new GMarker(point);
        GEvent.addListener(marker,”mouseover”, function() {
              marker.openInfoWindowHtml(place.address + ‘<br>’+'<b>Country:</b>’
              +place.AddressDetails.Country.CountryNameCode);
          });

           gmarkers[i] = marker;
           i++;
           map.addOverlay(marker);
  }
 </script>
  <form name=”mypickform” action=”/myPick” method=”get”>
  <body onload=”loadUserPicks()”>
  <div id=”map” style=”width: 800px; height: 600px”></div>
  </body>
  </form>
 </html>

Map

Enjoy……