Monday, January 19, 2015

Freeswitch mod_java with Launcher

To dynamically load classes in Freeswitch use this Laucher:
/*
 * Launcher.java
 *
 * Created on 13 September 2007, 06:40
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.freeswitch;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 *
 * @author dacha
 */
public class Launcher
{
    static
    {
        // Find and load mod_java
        String javaLibraryPaths = System.getProperty("java.library.path");
        String pathSeparator = System.getProperty("path.separator");
        String libraryPaths[] = javaLibraryPaths.split(pathSeparator);
        
        String libraryName = System.mapLibraryName("mod_java");
        int modJavaIndex = libraryName.indexOf("mod_java");
        if (modJavaIndex >= 0)
            libraryName = libraryName.substring(modJavaIndex);
        
        for (String libraryPath : libraryPaths)
        {
            String fullLibraryPath = libraryPath + File.separatorChar + libraryName;
            if (new File(fullLibraryPath).exists())
            {
                System.load(fullLibraryPath);
                break;
            }
        }
    }

    public static void launch(String sessionUuid, String args) throws Exception
    {
        String argv[] = args.split("[ ]");
        if (argv.length == 0)
        {
            System.out.println("Too few arguments to mod java");
            System.out.println("Usage: java /path/to/file.jar fully.qualified.class arg1 arg2 arg3");
            System.out.println("Usage: java fully.qualified.class arg1 arg2 arg3");
            return;
        }
        
        Class klazz=null;

        int argsOffset;
 System.out.println("argv[0]=" + argv[0]);
        if (argv[0].endsWith(".jar") || argv[0].endsWith(".JAR"))
        {
  System.out.println("in jar");
            if (argv.length < 2)
                throw new Exception("Too few arguments: must specify fully qualified class name when loading from JAR file");
     MyClassLoaderFromJar mycjar = new MyClassLoaderFromJar(argv[0]);
     klazz=mycjar.findClass(argv[1]);
            argsOffset = argv[0].length() + argv[1].length() + 2;
        }
        else
        {
          

            //klazz = Class.forName(argv[0]);
          try{
                 ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
                 MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
                
                 klazz = classLoader.loadClass(argv[0]);
                 
                
          } catch (Exception e) {
                 System.out.println("notice cannot load class!!!" + e.getMessage());
         }

            argsOffset = argv[0].length() + 1;
        }
        
        Constructor constructor = klazz.getConstructor();
        Object object = constructor.newInstance();
        Method run = klazz.getMethod("run", String.class, String.class);
        String newArgs = "";
        if (argsOffset < args.length())
            newArgs = args.substring(argsOffset);
        run.invoke(object, sessionUuid, newArgs);
    }
}

MyClassLoader class is a helper class that goes into mod_java/src/org/freeswitch along with Launcher

 package org.freeswitch;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;

class MyClassLoader extends ClassLoader{

        public MyClassLoader(ClassLoader parent) {
            super(parent);
        }

        public Class loadClass(String name) throws ClassNotFoundException {
            System.setSecurityManager(null);

            try {
                System.out.println("in load class");
                String url = "file:/usr/local/freeswitch/scripts/" + name + ".class";
                URL myUrl = new URL(url);
                URLConnection connection = myUrl.openConnection();
                InputStream input = connection.getInputStream();
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                int data = input.read();

                while(data != -1){
                    buffer.write(data);
                    data = input.read();
                }

                input.close();

                byte[] classData = buffer.toByteArray();

                Class cl = defineClass(name,
                        classData, 0, classData.length);
                System.out.println("class defined!!!!!!!!!!");
                return cl;

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }
    }

MyClassLoaderFromJar is another helper class to load classes from Jar

 package org.freeswitch;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.util.zip.*;
public final class MyClassLoaderFromJar extends ClassLoader {
    private final ZipFile file;

    public MyClassLoaderFromJar(String filename) throws IOException {
        this.file = new ZipFile(filename);
    }

    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
 System.out.println("in find class");
        ZipEntry entry = this.file.getEntry(name.replace('.', '/') + ".class");
        if (entry == null) {
            throw new ClassNotFoundException(name);
        }
 System.out.println("entry=" + entry);
        try {
            byte[] array = new byte[1024];
            InputStream in = this.file.getInputStream(entry);
            ByteArrayOutputStream out = new ByteArrayOutputStream(array.length);
            int length = in.read(array);
            while (length > 0) {
                out.write(array, 0, length);
                length = in.read(array);
            }
     System.out.println("returning class define");
            return defineClass(name, out.toByteArray(), 0, out.size());
        }
        catch (IOException exception) {
            throw new ClassNotFoundException(name, exception);
        }
    }
}

Put these files mod_java/src/org/freeswitch and do "make mod_java-install". The resulting mod_java.so is copied to /usr/local/freeswitch/mod. Note java.conf.xml sets the classpath for all the jars.


Scroller using Jquery



function scaleImage3(imageSrc, imageId, requiredWidth, requiredHeight) {
    // Create new off screen image to test
    var theImage = new Image();
    theImage.src = imageSrc;
    // Get accurate measurements from that.
    var width = theImage.width;
    var height = theImage.height;
    if ((width > 0) &&
        (height > 0)) {
     var horizontalMultiplier = requiredWidth / width;
     var verticalMultiplier = requiredHeight / height;
     var smallestMultiplier = Math.min(verticalMultiplier, horizontalMultiplier);

     // Get scaled sizes
     width *= smallestMultiplier;
     height *= smallestMultiplier;

     // Apply sizes to image
     $('#'+imageId).attr('width', width );
     $('#'+imageId).attr('height', height );
     $('#'+imageId).attr('src', imageSrc );
     $('#'+imageId).attr('style', {display :"inline"});
     var image_height=height;
     var arr = imageId.split("_");
     
     var accountId = arr[1];
     var originalListItemId = "listItem_" + accountId;
     var divHt=$("#scrollerDiv").css('height');
     divHt = divHt.replace('px', '');
     var top_margin = (divHt - image_height)/2;  
        //and change the margin-top css attribute to center the image
     if (imageId.indexOf("_clean") > -1) {
      var counter = arr[2];
         $("#listItem_" + accountId + "_" + counter + "_clean").css( 'margin-top' , top_margin);
     } else if (imageId.indexOf("_clone") > -1) {
      $("#listItem_" + accountId + "_clone").css( 'margin-top' , top_margin);
     } else {
      $("#listItem_" + accountId).css( 'margin-top' , top_margin);
     }
    }
}

/*
 * simplyScroll 2 - a scroll-tastic jQuery plugin
 *
 * http://logicbox.net/jquery/simplyscroll/
 *
 * Copyright (c) 2009-2012 Will Kelly - http://logicbox.net
 *
 * Dual licensed under the MIT and GPL licenses.
 *
 * Version: 2.0.5 Last revised: 10/05/2012
 *
 */
 
(function($,window,undefined) {

$.fn.simplyScroll = function(options) {
 return this.each(function() {
  new $.simplyScroll(this,options);
 });
};

var defaults = {
 customClass: 'simply-scroll',
 frameRate: 24, //No of movements per second
 speed: 1, //No of pixels per frame
 orientation: 'horizontal', //'horizontal or 'vertical' - not to be confused with device orientation
 auto: true,
 autoMode: 'loop', //auto = true, 'loop' or 'bounce',
 manualMode: 'end', //auto = false, 'loop' or 'end'
 direction: 'forwards', //'forwards' or 'backwards'.
 pauseOnHover: true, //autoMode = loop|bounce only
 pauseOnTouch: true, //" touch device only
 pauseButton: false, //" generates an extra element to allow manual pausing 
 startOnLoad: false, //use this to delay starting of plugin until all page assets have loaded
 //customization
 maxWidth: 650//customization: use this to set the width of the container for horizontal scrolling
};
 
$.simplyScroll = function(el,options) {
 
 var self = this;
 
 this.o = $.extend({}, defaults, options || {});
 this.isAuto = this.o.auto!==false && this.o.autoMode.match(/^loop|bounce$/)!==null;
 this.isHorizontal = this.o.orientation.match(/^horizontal|vertical$/)!==null && this.o.orientation==defaults.orientation; 
 this.isRTL = this.isHorizontal && $("html").attr('dir') == 'rtl';
 this.isForwards = !this.isAuto  || (this.isAuto && this.o.direction.match(/^forwards|backwards$/)!==null && this.o.direction==defaults.direction) && !this.isRTL;
 this.isLoop = this.isAuto && this.o.autoMode == 'loop' || !this.isAuto && this.o.manualMode == 'loop';
 // customization
 this.maxWidth = defaults.maxWidth || 650;
 this.supportsTouch = ('createTouch' in document);
 
 this.events = this.supportsTouch ? 
  {start:'touchstart MozTouchDown',move:'touchmove MozTouchMove',end:'touchend touchcancel MozTouchRelease'} : 
  {start:'mouseenter',end:'mouseleave'};
 
 this.$list = $(el); //called on ul/ol/div etc
 var $items = this.$list.children();
 
 //generate extra markup
 this.$list.addClass('simply-scroll-list')
  .wrap('
') .parent().wrap('
'); if (!this.isAuto) { //button placeholders this.$list.parent().parent() .prepend('
') .prepend('
'); } else { if (this.o.pauseButton) { this.$list.parent().parent() .prepend('
'); this.o.pauseOnHover = false; } } //wrap an extra div around the whole lot if elements scrolled aren't equal if ($items.length > 1) { var extra_wrap = false, total = 0; if (this.isHorizontal) { $items.each(function() { total+=$(this).outerWidth(true); }); extra_wrap = $items.eq(0).outerWidth(true) * $items.length !== total; } else { $items.each(function() { total+=$(this).outerHeight(true); }); extra_wrap = $items.eq(0).outerHeight(true) * $items.length !== total; } if (extra_wrap) { this.$list = this.$list.wrap('
').parent().addClass('simply-scroll-list'); if (this.isHorizontal) { this.$list.children().css({"float":'left',width: total + 'px'}); } else { this.$list.children().css({height: total + 'px'}); } } } if (!this.o.startOnLoad) { this.init(); } else { //wait for load before completing setup $(window).load(function() { self.init(); }); } }; $.simplyScroll.fn = $.simplyScroll.prototype = {}; $.simplyScroll.fn.extend = $.simplyScroll.extend = $.extend; $.simplyScroll.fn.extend({ init: function() { this.$items = this.$list.children(); this.$clip = this.$list.parent(); //this is the element that scrolls this.$container = this.$clip.parent(); this.$btnBack = $('.simply-scroll-back',this.$container); this.$btnForward = $('.simply-scroll-forward',this.$container); if (!this.isHorizontal) { this.itemMax = this.$items.eq(0).outerHeight(true); this.clipMax = this.$clip.height(); this.dimension = 'height'; this.moveBackClass = 'simply-scroll-btn-up'; this.moveForwardClass = 'simply-scroll-btn-down'; this.scrollPos = 'Top'; } else { this.itemMax = this.$items.eq(0).outerWidth(true); this.clipMax = this.$clip.width(); // customization var numClips = Math.round(this.maxWidth/this.clipMax); this.clipMax = numClips * this.clipMax; //if (this.clipMax > this.maxWidth) { //this.maxWidth = this.clipMax; //} this.dimension = 'width'; this.moveBackClass = 'simply-scroll-btn-left'; this.moveForwardClass = 'simply-scroll-btn-right'; this.scrollPos = 'Left'; } this.posMin = 0; this.posMax = this.$items.length * this.itemMax; var addItems = Math.ceil(this.clipMax / this.itemMax); //auto scroll loop & manual scroll bounce or end(to-end) if (this.isAuto && this.o.autoMode=='loop') { this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px'); this.posMax += (this.clipMax - this.o.speed); if (this.isForwards) { this.resetPosition = 0; //customization //this.$items.slice(0,addItems).clone(false).appendTo(this.$list); var counter=1; var itemsToFix=this.$items.slice(0,addItems).clone(true); counter=1; //assign ids to img elements for the scroller to work in IE9 $(itemsToFix).find('img').attr('id', function(idx, oldId){ var arr = oldId.split("_");var accountId=arr[1]; return "img_" + accountId + "_" + counter++ + "_clean";}); counter =1; //assign ids to li elements for the scroller to work in IE9 $(itemsToFix).each(function() { $(this).attr('id', function(idx, oldId){ var arr = oldId.split("_");var accountId=arr[1]; return "listItem_" + accountId + "_" + counter++ + "_clean";}); }); $(itemsToFix).appendTo(this.$list); this.$list.find("img").each(function() { scaleImage3($(this).attr('src'), $(this).attr('id'), 80, 80); }); } else { this.$items.slice(-addItems).clone(true).prependTo(this.$list); this.resetPosition = this.$items.length * this.itemMax; //due to inconsistent RTL implementation force back to LTR then fake if (this.isRTL) { this.$clip[0].dir = 'ltr'; //based on feedback seems a good idea to force float right this.$items.css('float','right'); } } //manual and loop } else if (!this.isAuto && this.o.manualMode=='loop') { this.posMax += this.itemMax * addItems; this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px'); this.posMax += (this.clipMax - this.o.speed); var items_append = this.$items.slice(0,addItems).clone(true).appendTo(this.$list); var items_prepend = this.$items.slice(-addItems).clone(true).prependTo(this.$list); this.resetPositionForwards = this.resetPosition = addItems * this.itemMax; this.resetPositionBackwards = this.$items.length * this.itemMax; //extra events to force scroll direction change var self = this; this.$btnBack.bind(this.events.start,function() { self.isForwards = false; self.resetPosition = self.resetPositionBackwards; }); this.$btnForward.bind(this.events.start,function() { self.isForwards = true; self.resetPosition = self.resetPositionForwards; }); } else { //(!this.isAuto && this.o.manualMode=='end') this.$list.css(this.dimension,this.posMax +'px'); if (this.isForwards) { this.resetPosition = 0; } else { this.resetPosition = this.$items.length * this.itemMax; //due to inconsistent RTL implementation force back to LTR then fake if (this.isRTL) { this.$clip[0].dir = 'ltr'; //based on feedback seems a good idea to force float right this.$items.css('float','right'); } } } this.resetPos() //ensure scroll position is reset this.interval = null; this.intervalDelay = Math.floor(1000 / this.o.frameRate); if (!(!this.isAuto && this.o.manualMode=='end')) { //loop mode //ensure that speed is divisible by item width. Helps to always make images even not odd widths! while (this.itemMax % this.o.speed !== 0) { this.o.speed--; if (this.o.speed===0) { this.o.speed=1; break; } } } var self = this; this.trigger = null; this.funcMoveBack = function(e) { if (e !== undefined) { e.preventDefault(); } self.trigger = !self.isAuto && self.o.manualMode=='end' ? this : null; if (self.isAuto) { self.isForwards ? self.moveBack() : self.moveForward(); } else { self.moveBack(); } }; this.funcMoveForward = function(e) { if (e !== undefined) { e.preventDefault(); } self.trigger = !self.isAuto && self.o.manualMode=='end' ? this : null; if (self.isAuto) { self.isForwards ? self.moveForward() : self.moveBack(); } else { self.moveForward(); } }; this.funcMovePause = function() { self.movePause(); }; this.funcMoveStop = function() { self.moveStop(); }; this.funcMoveResume = function() { self.moveResume(); }; if (this.isAuto) { this.paused = false; function togglePause() { if (self.paused===false) { self.paused=true; self.funcMovePause(); } else { self.paused=false; self.funcMoveResume(); } return self.paused; }; //disable pauseTouch when links are present if (this.supportsTouch && this.$items.find('a').length) { this.supportsTouch=false; } if (this.isAuto && this.o.pauseOnHover && !this.supportsTouch) { this.$clip.bind(this.events.start,this.funcMovePause).bind(this.events.end,this.funcMoveResume); } else if (this.isAuto && this.o.pauseOnTouch && !this.o.pauseButton && this.supportsTouch) { var touchStartPos, scrollStartPos; this.$clip.bind(this.events.start,function(e) { togglePause(); var touch = e.originalEvent.touches[0]; touchStartPos = self.isHorizontal ? touch.pageX : touch.pageY; scrollStartPos = self.$clip[0]['scroll' + self.scrollPos]; e.stopPropagation(); e.preventDefault(); }).bind(this.events.move,function(e) { e.stopPropagation(); e.preventDefault(); var touch = e.originalEvent.touches[0], endTouchPos = self.isHorizontal ? touch.pageX : touch.pageY, pos = (touchStartPos - endTouchPos) + scrollStartPos; if (pos < 0) pos = 0; else if (pos > self.posMax) pos = self.posMax; self.$clip[0]['scroll' + self.scrollPos] = pos; //force pause self.funcMovePause(); self.paused = true; }); } else { if (this.o.pauseButton) { this.$btnPause = $(".simply-scroll-btn-pause",this.$container) .bind('click',function(e) { e.preventDefault(); togglePause() ? $(this).addClass('active') : $(this).removeClass('active'); }); } } this.funcMoveForward(); } else { this.$btnBack .addClass('simply-scroll-btn' + ' ' + this.moveBackClass) .bind(this.events.start,this.funcMoveBack).bind(this.events.end,this.funcMoveStop); this.$btnForward .addClass('simply-scroll-btn' + ' ' + this.moveForwardClass) .bind(this.events.start,this.funcMoveForward).bind(this.events.end,this.funcMoveStop); if (this.o.manualMode == 'end') { !this.isRTL ? this.$btnBack.addClass('disabled') : this.$btnForward.addClass('disabled'); } } }, moveForward: function() { var self = this; this.movement = 'forward'; if (this.trigger !== null) { this.$btnBack.removeClass('disabled'); } self.interval = setInterval(function() { if (self.$clip[0]['scroll' + self.scrollPos] < (self.posMax-self.clipMax)) { self.$clip[0]['scroll' + self.scrollPos] += self.o.speed; } else if (self.isLoop) { self.resetPos(); } else { self.moveStop(self.movement); } },self.intervalDelay); }, moveBack: function() { var self = this; this.movement = 'back'; if (this.trigger !== null) { this.$btnForward.removeClass('disabled'); } self.interval = setInterval(function() { if (self.$clip[0]['scroll' + self.scrollPos] > self.posMin) { self.$clip[0]['scroll' + self.scrollPos] -= self.o.speed; } else if (self.isLoop) { self.resetPos(); } else { self.moveStop(self.movement); } },self.intervalDelay); }, movePause: function() { clearInterval(this.interval); }, moveStop: function(moveDir) { this.movePause(); if (this.trigger!==null) { if (typeof moveDir !== 'undefined') { $(this.trigger).addClass('disabled'); } this.trigger = null; } if (this.isAuto) { if (this.o.autoMode=='bounce') { moveDir == 'forward' ? this.moveBack() : this.moveForward(); } } }, moveResume: function() { this.movement=='forward' ? this.moveForward() : this.moveBack(); }, resetPos: function() { this.$clip[0]['scroll' + this.scrollPos] = this.resetPosition; } }); })(jQuery,window);

Use it in JSP




<div id="scrollerDiv">
      <ul class="myulclass" id="scroller">
        <s:iterator value="scrollerAccounts">
          <s:if test="profilePic != null && profilePic != ''">
           <li  id="listItem_${accountId}"><a href="host?number=${virtualNumber}"><img id="img_${accountId}" src="profile/${accountId}/${profilePic}" width="80" height="80"></a></li>
          </s:if>
          <s:elseif test="gender.description == \"Female\"">
           <li id="listItem_${accountId}"><a href="host?number=${virtualNumber}"><img id="img_${accountId}" src="img/noImageFemale.png" width="80" height="80"></a></li>
          </s:elseif>
          <s:else>
           <li id="listItem_${accountId}"><a href="host?number=${virtualNumber}"><img id="img_${accountId}" src="img/noImageMale.png" width="80" height="80"></a></li>
          </s:else>
        </s:iterator>
        <!--   called clones to ensure the clip is completely filled before the scrolling starts -->
        <s:iterator value="scrollerAccounts">
          <s:if test="profilePic != null && profilePic != ''">
           <li  id="listItem_${accountId}_clone"><a href="host?number=${virtualNumber}"><img id="img_${accountId}_clone" src="profile/${accountId}/${profilePic}" width="80" height="80"></a></li>
          </s:if>
          <s:elseif test="gender.description == \"Female\"">
           <li id="listItem_${accountId}_clone"><a href="host?number=${virtualNumber}"><img id="img_${accountId}" src="img/noImageFemale.png" width="80" height="80"></a></li>
          </s:elseif>
          <s:else>
           <li id="listItem_${accountId}_clone"><a href="host?number=${virtualNumber}"><img id="img_${accountId}" src="img/noImageMale.png" width="80" height="80"></a></li>
          </s:else>
        </s:iterator>
      </ul>
     </div>

Customizing ENUM in Hibernate


We create the GenericEnumUserType class as follows and use it like this in *.hbm.xml

<property name="responseCode" column="RESPONSE_CODE">
   <type name="net.mycompany.tps.domain.GenericEnumUserType">
    <param name="enumClass">net.mycompany.tps.domain.ExternalResponseCodeEnum</param>
   </type>
  </property>
Here is the net.mycompany.tps.domain.ExternalResponseCodeEnum NOTE the parseId method has to be a static
public enum ExternalResponseCodeEnum {
  ercNotSet(-1),
     ercInvalidCard(101),
     ercOTBDeclined(200),
     ercBlockedCard (210),
     ercBlockedANI(215),
     ercChargeback(220),
     ercBlockedRISK(222),
     ercExceededRiskParameters(230),
     ercCCWDeclined(271),
     ercFirstTimeCaller(280),
     ercSaleDeclined(300),
     ercOTBApproved(400),
     ercCCWTimeoutO(401),
     ercPositiveData(410),
     ercCCWApproved(421),
     ercSaleApproved(500),
     ercCCWTimeoutS(501);
     private int externalResponseCode;

    public static final Map lookupExternalResponseCodeEnum = new HashMap();

    static {
         //Create reverse lookup hash map 
         for(ExternalResponseCodeEnum d : ExternalResponseCodeEnum.values())
             lookupExternalResponseCodeEnum.put(d.getId(), d);
  }
  //constructor
  private ExternalResponseCodeEnum(int code) {
   this.externalResponseCode
   = code;
  }
  public int getId() {
   return externalResponseCode;
  }
  public static int parseId(int id) {
   return "set up the reverse lookup of enum based on id"
  }
}

import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.TypeResolver;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;


public class GenericEnumUserType implements UserType, ParameterizedType {

    private Class  enumClass;

    private Class  identifierType;

    private Method identifierMethod;

    private Method valueOfMethod;

    private static final String defaultIdentifierMethodName = "getId";

    private static final String defaultValueOfMethodName = "parseId";

    private AbstractSingleColumnStandardBasicType type;

    private int[] sqlTypes;

    @Override
    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enumClass");
        try {
            enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
        } catch (ClassNotFoundException exception) {
            throw new HibernateException("Enum class not found", exception);
        }

        String identifierMethodName =
                parameters.getProperty("identifierMethod",
                        defaultIdentifierMethodName);

        try {
            identifierMethod =
                    enumClass.getMethod(identifierMethodName, new Class[0]);
            identifierType = identifierMethod.getReturnType();
        } catch (Exception exception) {
            throw new HibernateException("Failed to optain identifier method",
                    exception);
        }

        TypeResolver tr = new TypeResolver();
        type =
                (AbstractSingleColumnStandardBasicType) tr.basic(identifierType
                        .getName());
        if (type == null) {
            throw new HibernateException("Unsupported identifier type "
                    + identifierType.getName());
        }
        sqlTypes = new int[] {type.sqlType()};

        String valueOfMethodName = parameters.getProperty("valueOfMethod",
                defaultValueOfMethodName);
        try {
            valueOfMethod = enumClass.getMethod(valueOfMethodName,
                            new Class[] {identifierType});
        } catch (Exception exception) {
            throw new HibernateException("Failed to optain valueOf method",
                    exception);
        }
    }

    @Override
    public Class returnedClass() {
        return enumClass;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
            throws HibernateException, SQLException {
        Object identifier = type.get(rs, names[0], null);
        if (identifier == null) {
            return null;
        }

        if (valueOfMethod == null) {

        }

        try {
            return valueOfMethod.invoke(enumClass, new Object[] {identifier});
        } catch (Exception exception) {
            throw new HibernateException(
                    "Exception while invoking valueOfMethod of enumeration class: ",
                    exception);
        }
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index)
            throws HibernateException, SQLException {
        try {
            Object identifier =
                    value != null ? identifierMethod.invoke(value,
                            new Object[0]) : null;
            st.setObject(index, identifier);
        } catch (Exception exception) {
            throw new HibernateException(
                    "Exception while invoking identifierMethod of enumeration class: ",
                    exception);

        }
    }

    @Override
    public int[] sqlTypes() {
        return sqlTypes;
    }

    @Override
    public Object assemble(Serializable cached, Object owner)
            throws HibernateException {
        return cached;
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        return x == y;
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public boolean isMutable() {
        return false;
    }

    public Object replace(Object original, Object target, Object owner)
            throws HibernateException {
        return original;
    }

 @Override
 public Object nullSafeGet(ResultSet arg0, String[] arg1,
   SessionImplementor arg2, Object arg3) throws HibernateException,
   SQLException {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 public void nullSafeSet(PreparedStatement arg0, Object arg1, int arg2,
   SessionImplementor arg3) throws HibernateException, SQLException {
  // TODO Auto-generated method stub
  nullSafeSet(arg0, arg1, arg2);
 }
}

Selenium Javascript


Selenium Script for Chrome Driver
package net.mycom.myapp.selenium;

import static org.junit.Assert.assertEquals;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class TestPopcornMultipleFunctionsMobile {
  private static WebDriver driver;

  //private static String baseUrl = "http://localhost:8080/";
  //private static String context="mycommyappWebsite/";
  private static String context="home?mobile=true";
  private static String baseUrl = "http://qa.i.opentalk.com/";
  
  private static String login = "seleniumnewuser";
  private static String password = "welcome";
  private static String changePassword = "welcome2";
  private static String testNumber = "2565137992";
  private static String testTextMsg = "hello there...testing with selenium";
  private static String facebookUserName;
  private static String facebookPassword = "";
        private static int countTestUsers = 1;
  private static String loginAs;
  
  @BeforeClass
  public static void setUp() throws Exception {
            for (int i = 1; i <= countTestUsers; i++) {
                System.setProperty("webdriver.chrome.driver", "C:\\Users\\Chrome\\chromedriver.exe");
                driver = new ChromeDriver();
//                driver = new FirefoxDriver();
             driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
             driver.get(baseUrl + context);
//             driver.get(baseUrl);
             System.out.println(baseUrl);
              assertEquals("Phone call | opentalk | Feed", driver.getTitle());
       driver.findElement(By.xpath("//a[@href='loginPage']")).getAttribute("href");
       driver.findElement(By.xpath("//a[@href='loginPage']")).click();
       login(i);
            }
  }
  @AfterClass
  public static void tearDown() throws Exception {
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='logout']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Login", driver.getTitle());
   driver.quit();
  }
  
  private static void login(int i) {
   loginAs = login + i + "@mycom.net";
   driver.findElement(By.id("emailOrPhone")).clear();
   driver.findElement(By.id("emailOrPhone")).sendKeys(loginAs);
   driver.findElement(By.id("password")).sendKeys(password);
   driver.findElement(By.name("submit")).click();
   assertEquals("Phone call |opentalk | Feed", driver.getTitle());
//   driver.findElement(By.id("menu")).click();
//         sendTextMessage();
        }
  
  //@Test
  public void checkTextHistory() throws Exception {
   driver.findElement(By.linkText("Text History")).click();
//   assertEquals("Text History", driver.getTitle().substring(0,12));
   //driver.findElement(By.xpath("//a[contains(@href,'popupMenu?')]")).click();
   List anchors = driver.findElememycom(By.xpath("//a[contains(@href,'popupMenu?')]"));
   Iterator j = anchors.iterator();
   while(j.hasNext()) {
    WebElement anchor = j.next();
    System.out.println(anchor.getAttribute("href"));
   }
  }
   
  //@Test
  public void sendTextMessage() throws Exception {
   driver.findElement(By.linkText("Call/Text")).click();
   assertEquals("Make Call / Send Text", driver.getTitle().substring(0,21));
   driver.findElement(By.id("sendText_to")).sendKeys(testNumber);
      driver.findElement(By.id("message")).sendKeys(testTextMsg);
   driver.findElement(By.id("sendTextButton")).click();
/*   for (String handle : driver.getWindowHandles()) {
       driver.switchTo().window(handle);
       if (driver.findElement(By.linkText("Send Text")).isDisplayed()) {
        driver.findElement(By.linkText("Send Text")).click();
        break;
       }
   } */
   // Check that we're back to the Text History screen. Don't rely on your variable
   assertEquals("Phone call | open Talk | Text History", driver.getTitle().substring(0,12));
  }
  
  @Test
  public void showHistory() throws Exception {
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='callHistory']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Call History", driver.getTitle().substring(0,36));
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='textHistory']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Text History", driver.getTitle().substring(0,36));
   
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='voicemail']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Voicemail", driver.getTitle().substring(0,33));
   
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='phoneBookListEntries']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Phonebook", driver.getTitle().substring(0,33));
   
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='displaySettingsMobile?appActiveTab=tab7']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Review Purchase", driver.getTitle().substring(0,39));
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='recentActiveAgemycomearch']")).getAttribute("href"));
      
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='displaySettingsMobile?hasResponseAction=false']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Setttings", driver.getTitle().substring(0,33));

        }

  //@Test
  public void showProfile() throws Exception {
   driver.findElement(By.xpath("//a[@href='home']")).click();
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='displaySettings']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.xpath("//li[@id='tab2Link']")).click(); //profile
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.xpath("//li[@id='tab3Link']")).click(); //phone & voicemail
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.xpath("//li[@id='tab4Link']")).click(); //time/date
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.xpath("//li[@id='tab5Link']")).click(); //privacy
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.xpath("//li[@id='tab6Link']")).click(); //profile picture
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.xpath("//li[@id='tab7Link']")).click(); //billing
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
  }

  @Test
  public void changePassword() throws Exception {
   //change password
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='displaySettingsMobile?hasResponseAction=false']")).getAttribute("href"));
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='changePassword']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.id("changePasswordConfirm_oldPassword")).sendKeys(password); 
   driver.findElement(By.id("changePasswordConfirm_newPassword")).sendKeys(changePassword); 
   driver.findElement(By.id("changePasswordConfirm_confirmNewPassword")).sendKeys(changePassword); 
   driver.findElement(By.id("blueButton")).click();
   assertEquals("Phone call |opentalk | Feed", driver.getTitle());
   
   //logout
   driver.findElement(By.id("toggleButton")).click();
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='logout']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Login", driver.getTitle());
   
   //logback with new password
         driver.get(baseUrl + context);
   driver.findElement(By.xpath("//a[@href='loginPage']")).getAttribute("href");
   driver.findElement(By.xpath("//a[@href='loginPage']")).click();
   driver.findElement(By.id("emailOrPhone")).clear();
   driver.findElement(By.id("emailOrPhone")).sendKeys(loginAs);
   driver.findElement(By.id("password")).sendKeys(changePassword);
   driver.findElement(By.name("submit")).click();
   
   //revert password
   driver.findElement(By.id("toggleButton")).click();
         driver.navigate().to(driver.findElement(By.xpath("//a[@href='displaySettingsMobile?hasResponseAction=false']")).getAttribute("href"));
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='changePassword']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Settings", driver.getTitle());
   driver.findElement(By.id("changePasswordConfirm_oldPassword")).sendKeys(changePassword); 
   driver.findElement(By.id("changePasswordConfirm_newPassword")).sendKeys(password); 
   driver.findElement(By.id("changePasswordConfirm_confirmNewPassword")).sendKeys(password);
   driver.findElement(By.id("blueButton")).click();   
   assertEquals("Phone call |opentalk | Feed", driver.getTitle());
//         System.out.println(driver.getTitle());
  }

  @Test
  public void forgotPassword() {
   //logback in
   driver.findElement(By.id("toggleButton")).click();
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='logout']")).getAttribute("href"));
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='passwordResetRequestInit']")).getAttribute("href"));
         System.out.println(loginAs);
   driver.findElement(By.name("emailOrPhone")).clear();
   driver.findElement(By.name("emailOrPhone")).sendKeys(loginAs);
   driver.findElement(By.name("Submit")).click();
   //logback in
         driver.get(baseUrl + context);
   driver.findElement(By.xpath("//a[@href='loginPage']")).getAttribute("href");
   driver.findElement(By.xpath("//a[@href='loginPage']")).click();
   driver.findElement(By.id("emailOrPhone")).clear();
   driver.findElement(By.id("emailOrPhone")).sendKeys(loginAs);
   driver.findElement(By.id("password")).sendKeys(password);
   driver.findElement(By.name("submit")).click();
   assertEquals("Phone call |opentalk | Feed", driver.getTitle());
  }

  //@Test
  public void facebookLogin() {
   facebookUserName = loginAs;
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='logout']")).getAttribute("href"));
   assertEquals("opentalk Login", driver.getTitle());
   driver.findElement(By.xpath("//img[@src='img/facebook_signin3.png']")).click();
   for (String handle : driver.getWindowHandles()) {
       driver.switchTo().window(handle);
       if (driver.findElememycom(By.id("email")).size() != 0) {
        driver.findElement(By.id("email")).clear();
        driver.findElement(By.id("email")).sendKeys(facebookUserName);
     driver.findElement(By.id("pass")).sendKeys(facebookPassword);
     driver.findElement(By.name("login")).click();
        break;
       }
   }
   assertEquals("Phone call | open Talk | opentalk Feed", driver.getTitle());
   
   //logout
   driver.navigate().to(driver.findElement(By.xpath("//a[@href='logout']")).getAttribute("href"));
   assertEquals("Phone call | open Talk | Login", driver.getTitle());
   
   //logback in
   driver.findElement(By.id("login_emailOrPhone")).clear();
   driver.findElement(By.id("login_emailOrPhone")).sendKeys(loginAs);
   driver.findElement(By.id("login_password")).sendKeys(password);
   driver.findElement(By.name("Submit")).click();
   assertEquals("Phone call | open Talk | opentalk Feed", driver.getTitle());
   
  }

  //@Test
  public void showPagination() throws Exception {
//   driver.findElement(By.xpath("//a[@href='home']")).click();
   driver.findElement(By.id("toggleButton")).click();
   driver.findElement(By.cssSelector("a > strong")).click();
   assertEquals("Phone call | open Talk | opentalk Feed", driver.getTitle());
  }


}
Firefox Driver
package net.mycom.myapp.selenium;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.concurrent.TimeUnit;

import net.mycom.myapp.domain.Account;
import net.mycom.myapp.domain.AccountPending;
import net.mycom.myapp.domain.dao.AccountDao;
import net.mycom.myapp.domain.dao.AccountDaoImpl;
import net.mycom.myapp.util.HibernateUtil;
import net.mycom.myapp.vn.dao.VirtualNumberDao;
import net.mycom.myapp.vn.dao.VirtualNumberDaoImpl;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.chrome.ChromeDriver;

public class TestmystuffMultipleUser {
 int countTestUsers = 10;
 private static WebDriver driver;

 // private static String baseUrl = "http://localhost:8080/";
 // private static String context = "mycommyappWebsite/";
 private static String context = "";
 //private static String dbUrl = "//mydb/myapp";
 //private static String dbUrl = "//mydb/myapp";
 private static String baseUrl = "http://qa.i.opentalk.com/";
 private static String dbUrl = "//mydbqa.i.mystuff.com/myapp";

 private static String dbLogin = "myapp_web";
 private static String dbPassword = "welcome";
 private static String dbShowSql = "true";
 private static String firstName = "Selenium";
 private static String lastName = "Newuser";
 private static String email = "seleniumNewUser";
 private static String password = "welcome";
 private static String areaCode = "818";
 int terminal = 5555000;
 private static String terminalString = "";

 private static String gender[] = { "Male", "Female" };

 @BeforeClass
 public static void setUp() throws Exception {
  HibernateUtil.setConnectionParameters(dbUrl, dbLogin, dbPassword,dbShowSql);
     System.out.println("Before  FireFox");
        System.setProperty("webdriver.chrome.driver", "C:\\Users\\Chrome\\chromedriver.exe");
        driver = new ChromeDriver();
//  driver = new FirefoxDriver();
  driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
     System.out.println("After  FireFox");
 }

 @AfterClass
 public static void tearDown() throws Exception {
  driver.quit();
 }

 @Test
 public void newUserWithoutVN() throws Exception {
  // loop to check, delete, and create the accoumycom
     System.out.println("Before  Loop");

  for (int i = 0; i < countTestUsers; i++) {

   driver.get(baseUrl + context + "home");
   assertEquals("mystuff Login", driver.getTitle());
   terminal = terminal + i;
   terminalString = areaCode + terminal;
   System.out.println(terminalString);

   Session session = HibernateUtil.getCurremycomession();
   Criteria crit = session.createCriteria(Account.class);
   crit.add(Restrictions.eq("terminatingNumber", terminalString));
   Account ac = (Account) crit.uniqueResult();
   // Delete account if it exists
   if (ac != null) {
    Transaction tran = session.beginTransaction();
    VirtualNumberDao vnDao = new VirtualNumberDaoImpl(null);
    vnDao.deprovision(ac.getAccountId());
    AccountDao accountDao = new AccountDaoImpl();
    accountDao.deleteAccount(ac.getAccountId());
    tran.commit();
   }

   driver.findElement(By.id("signup_firstName")).clear();
   driver.findElement(By.id("signup_firstName")).sendKeys(
     firstName + i);
   driver.findElement(By.id("signup_lastName")).clear();
   driver.findElement(By.id("signup_lastName")).sendKeys(lastName + i);
   driver.findElement(By.id("signup_email")).clear();
   driver.findElement(By.id("signup_email")).sendKeys(
     email + i + "@mycom.net");
   driver.findElement(By.id("signup_email2")).clear();
   driver.findElement(By.id("signup_email2")).sendKeys(
     email + i + "@mycom.net");
   driver.findElement(By.id("signup_password")).clear();
   driver.findElement(By.id("signup_password")).sendKeys(password);
   driver.findElement(By.id("signup_gender")).sendKeys(password);
   Select select = new Select(driver.findElement(By
     .id("signup_gender")));
   // select.deselectAll();
   select.selectByVisibleText(gender[i % 2]);

   driver.findElement(By.xpath("//input[@value='Sign Up']")).click();
   session.close();

   // Reset connection so we can see new inserts
   session = HibernateUtil.getCurremycomession();

   // get from db account pending
   crit = session.createCriteria(AccountPending.class);
   crit.add(Restrictions.eq("email", (email + i + "@mycom.net")));
   crit.addOrder(Order.desc("idAccountPending"));
   crit.setMaxResults(1);
   AccountPending ap = (AccountPending) crit.uniqueResult();
   if (ap == null) {
    fail("could not read account pending");
   }

   // Generate url that the email would send
   String emailCode = ap.getEmailCode();
   driver.navigate().to(
     baseUrl + context + "/emailConfWoVn?id="
       + ap.getIdAccountPending() + "&emailCode="
       + emailCode);

   // terminatingNumber.jsp
   driver.findElement(By.name("areaCode")).sendKeys(areaCode);
   driver.findElement(By.name("teleport")).sendKeys(
     terminalString.substring(3, 6));
   driver.findElement(By.name("terminal")).sendKeys(
     terminalString.substring(6, 10));
   driver.findElement(By.xpath("//input[@value='Continue']")).click();

   // ivrTnVerification.jsp
   driver.findElement(By.xpath("//input[@value='Continue']")).click();

   long accountPendingId = ap.getIdAccountPending();
   session.evict(ap);
   session.close();
   session = HibernateUtil.getCurremycomession();
   ap = (AccountPending) session.get(AccountPending.class,
     accountPendingId);
   Transaction tran = session.beginTransaction();
   ap.setTnCodeVerified(true);
   session.saveOrUpdate(ap);
   tran.commit();

   // ivrTnVerificationConfirm.jsp
   driver.findElement(By.xpath("//input[@value='Continue']")).click();

   // chooseAreaCode.jsp
   driver.findElement(By.xpath("//input[@value='Continue']")).click();

   // chooseVn.jsp
   driver.findElement(By.xpath("//input[@value='Continue']")).click();

   // accountCreated.jsp
   driver.findElement(By.xpath("//input[@value='Go To My Account']"))
     .click();
   driver.navigate().to(
     driver.findElement(By.xpath("//a[@href='logout']"))
       .getAttribute("href"));
   assertEquals("mystuff Login", driver.getTitle());

  }
 }
}

FB Authentication


FB Authentication
•  User clicks on the FB button on home page
•  the user is redirected to https://graph.facebook.com/oauth/authorize with these parameters:

client_id FB App Id
type web_server
display Popup
redirect_uri /myServices/connectToFBCallback
response_type Token
auth_type Reauthenticate
state Test
scope Email

• Note that  is set up in the FB App at developers.facebook.com

• after the user logs successfully into FB, the callback URL (/myServices/connectToFBCallback) is invoked by FB we are interested in the 2 parameters that are passed into the callback URL.

1) code
2) state

•  if code is null or empty, we assume the user is not authorized by FB and send the user to registration

•  state should be same as the one we passed with the  URL https://graph.facebook.com/oauth/authorize 

•  if state is null or empty, we assume the user is not authorized by FB and send the user to  registration

• Note: if the callback URL is never invoked by FB, there is nothing that we can do
 to inform the user about the status of their login

• the next step is to get the access token

•  the URL is https://graph.facebook.com/oauth/access_token

• parameters:

client_id 
code 
type web_server
client_secret 

•  open the URL connection is https://graph.facebook.com/oauth/access_token using HTTPS protocol and read the input. We are interested in the access token that could be read in the input as access_token=xyz...

• Save the access token in the Database

• We then need to get the FB username of the user 

•  open HTTPS URL connection to https://graph.facebook.com/me

• with parameter

 access_token=

•  the response from FB is read into a Gson object 
•  the username and email are parsed and stored in the Gson object
•  we then look up the   Account table using the email of Gson object
1) if the account is found, we log the user in and we are done
2) if the account is not found, we send the user to registration

Logging in FB User

• We redirect the user to myWebsite/loginFB.action with the following parameters:

1) email (ex:abc@abc.com)
2) profilePic (ex: https://graph.facebook.com//picture)

• The loginFB method will store the profile pic in  Account.profile_pic.

• For example: https://graph.facebook.com/gandikotam/picture will  be the value stored in the Account.profile_pic for the FB user with username gandikotam

• To retrieve the image, the ProfilePicController needs to be modified to download the image using HTTPS protocol.

Sample mobile JSP


<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
 <head>
  <title><%= myappProperties.sitePageTitle() %> Action Menu</title>
  <s:head />
  <jsp:include page="/mobile/mobileScriptsAndStyles.jsp"></jsp:include>
  <style type="text/css">
   p img {
    max-width: 100%;
   }
  </style>
  
  <script type="text/javascript" src="js/mobile/scaleImage.js"></script>
  <script type="text/javascript">
   $("div[data-role='page']").live("pageshow", function(event, ui) {
    <s:if test="account.profilePic != null && account.profilePic != ''">
     scaleImage("profile/${account.accountId}/${account.profilePic}", "profilePicture2", 60, 60);
    </s:if>
    <s:elseif test="genderOfPhoneBookEntry == \"F\"">
     scaleImage("img/noImageFemale.png", "profilePicture2", 60, 60);
    </s:elseif>
    <s:else>
     scaleImage("img/noImageMale.png", "profilePicture2", 60, 60);
    </s:else>
   });
  </script>
 </head>

 <body>
  <div data-role="page" data-theme="c">
   <div data-role="content" style="background-color:#FFFFFF;">
    <!-- Menu button -->
    <div id="toggleButton" onclick="toggleMenu();" style="width: 26px; height: 26px; background: url(img/mobile/list.png) 0 0 no-repeat; cursor: pointer; float: left;"></div>
    <!-- Menu overlay -->
    <div id="menuClickOverlay">
     <%@ include file="/mobile/logo.jsp" %><br />
     
     <div data-role="content">
      <%@ include file="/mobile/popupCommon.jsp" %>
      <div id="agentProfile" style="width: 100%; min-width: 0px; line-height:auto; margin-top:0px;">
       ${account.profilePageHtml}
      </div>
     </div>
    </div>
    <!-- /Menu overlay -->
    <!-- Menu -->
    <%@ include file="/mobile/mobileMenu.jsp" %>
    <!-- /Menu -->
   </div>
   
   <jsp:include page="/mobile/navbar.jsp"></jsp:include>
  </div>
 </body>
</html>

mobileScriptsAndStyles.jsp
<%@page import="net.mycom.myapp.misc.myappProperties" %>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="format-detection" content="telephone=yes">

<link rel="apple-touch-icon-precomposed" href="img/mobile/apple-touch-icon.png" />
<link rel="apple-touch-startup-image" href="img/mobile/apple-touch-startup-image.png" />

<link rel="stylesheet" href="css/mobile/jquery.mobile-1.2.0.min.css" />
<link rel="stylesheet" href="css/mobile/jquery.mobile-1.1.0.c_mycom.css" />

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
 $(document).bind("mobileinit", function() {
  $.mobile.ajaxEnabled = false;
  $.mobile.hashListeningEnabled = false;
 });
</script>
<script type="text/javascript" src="js/mobile/jquery.mobile-1.2.0.min.js"></script>

<link href="css/style.css" rel="stylesheet" type="text/css" />
<link href="css/<%= myappProperties.siteTheme() %>.css" rel="stylesheet" type="text/css" />


<style type="text/css">
 /* Menu
  */
 .ui-btn-text,
 .ui-btn input, .ui-btn button,
 .ui-checkbox, .ui-radio,
 .ui-checkbox input, .ui-radio input,
 .ui-checkbox .ui-btn, .ui-radio .ui-btn,
 .ui-select .ui-btn select {
  z-index: 0;
 }
 
 /* Counters on menu */
 .ui-li-count {
  display: none;
 }
 /* /Menu
  */
  /* prevent zooming */
  .ui-select .ui-btn select{font-size: 50px;}
</style>

<jsp:include page="/analytics.jsp" />

Sample Ajax call using Jquery


function getNewAccountsHtml() {
 $.ajax({
     type: 'GET',
     cache: false,
     async: false,
     url: 'getXXX?hours=' + <%= Integer.parseInt(Properties.Hours())%>,
     data: $("#id").serialize(),
     success: function(data) {
      $("#newAccountsHtml").html(data.xyz); //the java method sets html.put("xyz", "value") and struts.xml has the action configured
      $("#newAccountsHtml").css("display", "block");
      $("#newAccountsUpdateTime").html(getCurrentTimestamp());
     },
     error: function(XMLHttpRequest, textStatus, errorThrown) {
         alert("Server Unavailable");
     },
     dataType: "json"
 });
}