Pages

Friday, November 19, 2010

Google Maps API issue with popup window sizing

Several times as part of my work with the Google maps API now, I have seen cases where the content of an info window popup falls below the bottom end of the window.

This occurs when the API has trouble calculating the size of the content before it has loaded. For example it occurs frequently with images where the image size is not specified, inherited styles (as font size is calculated using a default font, which may not be the one specified in the CSS), and tables where the width is not specified exactly.

For example something like this does not work when cell data flows over multiple rows:

 <table border="1" cellspacing="1" cellpadding="3" width="100%" bgcolor="#EAF0F8">
...
</table>

Whereas this does:
 
 <table border="1" cellspacing="1" cellpadding="3" width="600px" bgcolor="#EAF0F8">
...
</table>
 

Friday, October 8, 2010

setting Extjs Menu maximum height

I was recently trying to set the maximum height of an Extjs.menu.Menu and wasted way too much time on it, including posting on the Sencha forums and waiting in vain for a reply. But I now have a solution, and here it is, for the greater good of humanity...

What I tried that failed was something like:


 menu = new Ext.menu.Menu({  
                 id: 'menu',  
                 style: '',  
                 items: items,  
                 renderTo: 'center_region',  
                 showSeparator: false,  
                 maxHeight: 100,  
                 autoScroll: true,  
                 enableScrolling: true  
   
               });  
   
               menu.showAt([x, y]);
I tried various settings of autoHeight, style, etc. as well and nothing seemed to work. Adding the height attribute (height: 100) actually made a difference, but it now set the height permanently to 100px rather that a maximum of 100px, which resulted in a number of unsightly gaps at the bottom of the menu when the number of items was small.

The solution that finally worked for me was the following:


               reportsMenu = new Ext.menu.Menu({  
                 id: 'reportsMenu',  
                 showSeparator: false,  
                 boxMaxHeight: 150,  
                 autoScroll: true,  
                 enableScrolling: true,  
                 items: selectedReports  
               });  
   
               reportsMenu.showAt([x, y]);  
               reportsMenu.syncSize();
How one is supposed to figure that out from the Ext documentation beats me (unless hours of trial and error is intended). FYI I was using Extjs 3.1.1, in case it is ever updated to be more intuitive and the meaning of properties changes in future.

Tuesday, October 5, 2010

Extjs Store not loading

I recently came across the problem of my Extjs Store not loading anything, with no apparent errors. My Ext.data.Store loads data from a remote server and uses a Ext.data.ArrayReader with a converter for one of the fields, like:

    var genericFeaturesStore = new Ext.data.Store({
    proxy: new Ext.data.HttpProxy({url: 'getRecords.do'}),

    reader: new Ext.data.ArrayReader({}, [

        { name: 'title' },
        { name: 'records', convert : convertRecords}
    ]),
    ...
    });

The converter looks like this:

    var convertRecords = function(v, record) {
        for (var i = 0; i < v.length; i++) {
            v[i] = new Record(
                    v[i].title,
                    v[i].description,
                    v[i].serviceType,
                    v[i].serviceURLs,
                    v[i].keywords);
        }
        return v;
    };


The problem I had was that the convertRecords() seemed to begin execution but not complete, although the application was not stuck but appeared as if convertRecords() had returned.


The solution, which should help for any generic Store loading (or not loading) problem:

    genericFeaturesStore.on({
        'load': {
            fn: function(store, records, options) {
                alert("load");
            },
            scope: this
        },
        'loadexception': {
            fn: function(obj, options, response, e) {
                alert("error: "+e);
            },
            scope: this
        }
    });


This allowed me to see that it was throwing an error because it couldn't find the serviceType for one of the many records.
              

Thursday, September 9, 2010

Setting the scope of callbacks with Extjs

I recently ran into a problem where I was attempting to access a record in a collection being iterated over from inside a GDownloadUrl (Google Maps API) callback whose request would be executed as part of that loop. It took me a while to figure out the reason the last record was always getting passed to the callback no matter which callback was executing - GDownloadUrl is asynchronous and by the time any of the callbacks are executed the iteration was usually over!

Extjs provides an easy alternative to GDownloadUrl that allows access to the iteraiton record (or any other object) used when executing the callback - Ext.Ajax. All that needs to be done to retain the object required in the callback is to call createDelegate on the callback and then access the object in the callback using "this". An example is provided below:

for (var i = 0; i < activeLayersStore.getCount(); i++) {

    var record = activeLayersPanel.getStore().getAt(i);

    Ext.Ajax.request({
        url: url,
        timeout        : 180000,
        success: function(response, options) {
        alert("The record for this iteration is: "+ this.get('TypeName'));
        }.createDelegate(record),
        failure: function(response, options) {
            alert("Error requesting data" + response.statusText);
        }
    });

}

The documentation for Extjs Function.createDelegate can be found here: http://dev.sencha.com/deploy/dev/docs/?class=Function&member=createDelegate

Additionally,  if multiple objects are required for use in the callback, the createDelegate may be used as follows:


yourFunction.createDelegate({ o1: obj1, o2: obj2 });

or alternatively, if the signature of your handler is flexible you can pass parameters as follows:
yourFunction.createDelegate(scope, [scope2], 2); 

Friday, September 3, 2010

Image Zoom in Javascript

I recently spent some time investigating how to achieve image zoom using Javascript (as Extjs doesn't support it as of v3). There may be simpler jquery or other ways to achieve this but I wanted some simple Javascript. Suppose we have a couple of synced Extjs images and panels defined as follows:

        /**
         * The first image (BoxComponent)
         */
        var imgBox1 = new Ext.ux.Image({
            id: 'img_box1',   
            src:'http://earthobservatory.nasa.gov/Features/BlueMarble/Images/land_shallow_topo_2048.jpg'
        });

       
        /**
         * Panel for the first image
         */
        var imgPanel1 = new Ext.Panel({
            id: 'img_panel1',
            title: "Migrated",
            height: 280,
            autoScroll: true,
            items:[imgBox1],
            listeners: {
                render: function(p){
                    //sync scrolling between image panel 1 and 2
                    p.body.on('scroll', function(e){
                        var panel2 = Ext.getCmp('img_panel2').body.dom;
                        panel2.scrollLeft = e.target.scrollLeft; 
                        panel2.scrollTop = e.target.scrollTop;
                    }, p);
                  }
                }
        });
       
        /**
         * The second image (BoxComponent)
         */
        var imgBox2 = new Ext.ux.Image({
            id: 'img_box2',
            src:'http://earthobservatory.nasa.gov/Features/BlueMarble/Images/land_shallow_topo_2048.jpg'
        });
       
        /**
         * Panel for the second image
         */
        var imgPanel2 = new Ext.Panel({
            id: 'img_panel2',
            title: "Stacked",
            height: 280,
            autoScroll: true,
            items:[imgBox2],
            listeners: {
                render: function(p){
                    //sync scrolling between image panel 1 and 2
                    p.body.on('scroll', function(e){
                        var panel1 = Ext.getCmp('img_panel1').body.dom;
                        panel1.scrollLeft = e.target.scrollLeft; 
                        panel1.scrollTop = e.target.scrollTop;
                    }, p);
                  }
                }
        });

Zoom can be achieved as follows:

    /**
     * Add zoom functionality to image panels
     */
    'addZoom': function() {
   
        var zooming=function(e){
            e=window.event ||e;
            var o=this,data=e.wheelDelta || -e.detail*40,zoom,size;
                
            //TODO: Zooming in IE doesn't zoom to the correct point?
            if(!+'\v1'){//IE
                var oldWidth=o.offsetWidth;
                var oldHeight=o.offsetHeight;       
   
                zoom = parseInt(o.style.zoom) || 100;
                zoom += data / 12;
                if(zoom > zooming.min)
                    o.style.zoom = zoom + '%';
                e.returnValue=false;
   
                var newWidth=o.offsetWidth*zoom/100;
                var newHeight=o.offsetHeight*zoom/100;
                var scrollLeft = (o.parentNode.scrollLeft/oldWidth)*newWidth;
                var scrollTop = (o.parentNode.scrollTop/oldHeight)*newHeight;
               
                o.parentNode.scrollLeft = scrollLeft;
                o.parentNode.scrollTop = scrollTop;
            }else {
                size=o.getAttribute("_zoomsize").split(",");
                zoom=parseInt(o.getAttribute("_zoom")) ||100;
                zoom+=data/12;
               
                var oldWidth=o.offsetWidth;
                var oldHeight=o.offsetHeight;
                var newWidth=size[0]*zoom/100;
                var newHeight=size[1]*zoom/100;
                var scrollLeft = (o.parentNode.scrollLeft/oldWidth)*newWidth;
                var scrollTop = (o.parentNode.scrollTop/oldHeight)*newHeight;  
   
                if(zoom>zooming.min){
                    o.setAttribute("_zoom",zoom);
                    o.style.width=newWidth+"px";
                    o.style.height=newHeight+"px";
                    //TODO: Zoom is very jerky when setting scrollbars this way, when
                    // either scrollbar is not at position 0. Need to fix it.
                    o.parentNode.scrollLeft = scrollLeft;
                    o.parentNode.scrollTop = scrollTop;
                }
                e.preventDefault();
                e.stopPropagation();//for firefox3.6
            }
        };
   
        zooming.add=function(obj,min){// obj = image box, min defines the minimum image zoom size ,defaults to 50
            zooming.min=min || 50;
            obj.onmousewheel=zooming;
            if(/Firefox/.test(navigator.userAgent))//if Firefox
                obj.addEventListener("DOMMouseScroll",zooming,false);
            if(-[1,]){//if not IE
                    obj.setAttribute("_zoomsize",obj.naturalWidth+","+obj.naturalHeight);
            }
        };
       
        zooming.add(document.getElementById("img_box1"));  
        zooming.add(document.getElementById("img_box2"));      
    }

The above zoom function is as far as I got with it before having to put it aside. As you may notice from the comments, it doesn't work that nicely in IE and setting of the scrollbars is quite jerky when setting both scrollLeft and scrollTop to somthing other than position 0. This is something I will need to investigate further and update here in future.

Sunday, August 8, 2010

Learning Ext JS

Ext JS is a javascript library for building web applications, originally an extension of YUI.

The API documentation can be found at http://dev.sencha.com/deploy/dev/docs/

An excellent source for learning Ext JS are the YouTube tutorials by Jay Garcia from TDG-innovations (http://tdg-i.com/ has the screencasts with a better quality than those on YouTube). Some topics they have covered include:

  • Ext.extend - subclassing with Ext JS
  • Ext.apply - a utility that allows one to easily copy properties over from one object to anothe
  • Ext.each - an alternative to a for loop, used to iteratie over an array (this one gets a little hairy in the screencast, I'm not sure how useful it really is)
  • Containers (Ext.Panel, Ext.Window - add, remove, doLayout, Ext.Element, Ext.Fx - slideOut, fadeOut)
  •  

Tuesday, July 13, 2010

Inversion of Control

A common issue faced by enterprise application builders is how to fit together different elements, such as web controller architectures with DB interfaces, when they were built by different teams with little knowledge of eachother. IoC literally inverts control so that instead of application code calling libraries, libraries call the application code based on events occurring.

A good example of early IoC is the change in UIs, from being controlled by the application workflow, to GUIs which are controlled by events.

Another term for IoC is dependency injection, introduced by Martin Fowler, which is explained as follows: "The basic idea of Dependency Injection is to have a separate object, an assembler, that populates a field in X class with an implementation for Y interface."

JBoss Application Server Overview

JBoss is a J2EE compatible application server that has full support for J2EE web services and the SOA. It supports the AOP model for developing middleware solutions and integrates well with Hibernate (object persistence framework).

The JBoss architecture consists of the microcontainer, bootstrap beans loaded into the microcontainer, a collection of deployers for loading various deployment types, and various mbean (managed beans - Java objects that represent resources to be managed) and legacy mbean deployments.

The JBoss Microcontainer is a lightweight container for managing POJOs, their deployment, configuration, and lifecycle.

You don't have to run a monolithic server all the time, but may remove components that are not required and integrate additional services as required, into JBoss by writing your own mbeans.
 
The JBoss AS ships with a number of different server configurations:
<JBoss_Home>\server\
    • minimal - bare-bones server, no web container, EJB, or JMS support
    • default - a default set of services
    • standard - the Java EE5 certified configuration of services
    • all - all available services
    • web - lightweight web container-oriented configuration of services
      To find out which services are configured in each configuration you can check
      <JBoss_Home>\server\<instance-name>\deployers or deploy.

      JBoss provides an embedded Hypersonic database along with a default datasource to connect applications to.

      When the JBoss server is running, you can get a live view of the server by going to the JMX console application. This is a raw view of JMX beans which make up the server.

      In JBoss, log4j is used for logging, controlled by conf/jboss-log4j.xml. The default output file is the server.log.


      The JBoss AS comes with clustering support out of the box. Ina JBoss cluster, a node is a JBoss server instance. A cluster (partition) contains a set of nodes that work toward some goal. The JBoss AS supports two types of clustering architectures - client side interceptors (proxies/stubs), and load balancers.

      Monday, July 12, 2010

      JSP Overview

      JSP is a popular Java technology for web application development and is based on servlet technology. A JSP page is a text document that contains two types of text - static data which can be expressed in any text-based format (HTML, SVG, XML, etc) and JSP elements (standard JSP or XML) which construct dynamic content.

      A JSP page services requests as a servlet. In an application server, the source for the servlet created from a JSP named myPage is myPage_jsp.java. Once the JSP has been translated and compiled, the page's servlet follows the standard servlet lifecycle.

      Expressions that are evaluated immediately use the ${ } syntax. Expressions that are differed use the #{ } syntax. Immediate evaluation expressions are always read-only value expressions.

      Implicit objects include:
      • PageContext
      • Servlet Context
      • Session
      • Request
      • Response
      • etc.
      JSP technology directly supports JavaBeans components with standard JSP language elements:
      • The JSP:useBean element declares that the page will use a bean that is stored within and is accessible from the specified scope (application, session, request, or page)
      • jsp:setProperty
      • jsp:getProperty
      Custom tags are user-defined JSP language elements that encapsulate recurring tasks. A tag handler is an object that implements a custom tag. When a JSP page containing a custom tag is translated into a servlet, the tag is converted into operations on a tag handler. The web container then invokes those operations when the JSP page's servlet is executed.

      To declare that a JSP page will use tags defined in a tag library, include the taglib directive.

      An Applet or JavaBeans component can be included in a JSP by using the jsp:plugin element.

      Friday, July 9, 2010

      The REST architectural style

      REST, Representational State Transfer, is an architural style that captures (post-hoc) the characteristics of the Web that made it so successful. It is a simpler alternative to SOAP and WSDL-based Web Services, where a representation of the requested resource is returned.

      A concrete implementation of a REST web service follows four basic design principles:
      • Uses HTTP methods explicitly (POST, GET, PUT, DELETE)
      • Stateless
      • Exposes directure structure
      • Transfer XML, Javascript Object Notation, or both
      In the Web Services world, REST is a key design idiom that embraces a stateless client-server architecture in which the web services are viewed as resources and can be identified by their URIs.

      The JAX-RS provides full support for building and deploying RESTful web services. It offers a number of utility classes and interfaces, and declarative annotations that allow you to:
      • Identify components of the application
      • route requests to particular methods/classes
      • extract data from requests into arguments of methods
      • provide metadata used in responses

      Hibernate

      Hibernate is a Java framework that provides OR mapping functionality to define how Java objects are stored, modified, deleted, and retrieved.

      The Hibernate architecture has 3 main components:
      • connection management
      • transaction management
      • object-relational mapping
      Hibernate uses POJO classes and XML mapping files to map to database tables.

      The Hibernate Session is the main runtime interface between a Java application and Hibernate. SessionFactory allows the application to create a Hibernate Session by reading the configuration from hibernate.cfg.xml.

      Important elements of the Hibernate mapping file include the following:
      • <hibernate-mapping> root element
      • <class> maps classes to DB entities
      • <id> maps to the primary key of a table
      • <generator> is used to generate the primary key for a new record. Values include increment, sequence, and assigned
      • <property> maps attributes to columns
      HQL is based on the relational object models and makes SQL object-oriented. It uses classes and proeprties instead of tables and columns. It supports polymorphism, associations, etc. and returns results as objects. It is also database independent.

      Hibernate also supports native SQL statements.

      SOAP vs other protocols

      SOAP (Simple Object Access Protocol) is an XML-based protocol that allows objects of any kind (Java, COM, etc.) on any platform and in any language to communicate. SOAP follows a RPC-style request/response mechanism. Data can be serialised without regard to any specific transport protocol, although HTTP is typically the protocol of choice.

      RMI, SOAP's chief competitor, is the process of activating a method on a remotely running object. Java RMI provides a mechanism for supporting distributed computing.
      In RMI, a remote method is invoked directly through a remote object's stub.The invocation and results are encoded across the network. The biggest advantage here is:
      • type-safety - the direct use of method names is possible and compile-time errors occur if arguments are incorrect
      Conversely, an RPC-style call (eg: SOAP) sends a request message to the remote server, which formulates the response and sends it back. The client does not invoke a method directly. The main advantage of the RPC style is:
      • greater independence between client and server

      Monday, July 5, 2010

      Overriding HashCode

      Overriding the default implementations of the Java class equals method provides a higher degree of semantic comparability between object instances. Under the default implementation, two references are equal only if they refer to the exact same object.

      Cases where hashCode must be overridden include the following:
      • if a class overrides the equals method it must override hashCode
      • when they are both overridden, equals and hashCode must use the same set of fields
      • if two objects are equal, then their hashCode values must be equal as well
      If equals() and hashCode() are not overridden, no adverse effects would occur unless the objects are used in a HashMap or other hash-based collection. If such objects are used in hash-based collections, we would not be able to reliably retrieve objets unless we used exactly the same object instance in the get() call as was used in the put() call.

      A simple way of overriding the equals and hashcode methods in Eclipse is to generate them using the menu/context menu Source -> Generate hashCode() and equals().

      All hash-based collections assume that an object's hash value will not change whilst it is in use as a key in the collection. If assumption were violated unpredictable results would occur.

      PL/SQL Overview

      PL/SQL bridges the gap between database technology and procedural programming languages. PL/SQL allows the use of SQL statements to manipulate Oracle data and flow-of-control statements to process the data. You can also:
      • declare constants and variables
      • define procedures and functions
      • trap runtime errors.
      A PL/SQL program is made up of logical blocks, containing any number of nested sub-blocks that group logically related declarations, statements, and exception handling together. 


      And example PL/SQL script is given below (taken from Oracle docs):


      DECLARE
         qty_on_hand  NUMBER(5);
      BEGIN
         SELECT quantity INTO qty_on_hand FROM inventory
            WHERE product = 'TENNIS RACKET'
            FOR UPDATE OF quantity;
         IF qty_on_hand > 0 THEN  -- check quantity
            UPDATE inventory SET quantity = quantity - 1
               WHERE product = 'TENNIS RACKET';
            INSERT INTO purchase_record
               VALUES ('Tennis racket purchased', SYSDATE);
         ELSE
            INSERT INTO purchase_record
               VALUES ('Out of tennis rackets', SYSDATE);
         END IF;
         COMMIT;
      END;
      

      Control structures are the most important PL/SQL extension to SQL. PL/SQL provides the following control structures:
      • if-then-else
      • case
      • for loop
      • while loop
      • exit when
      • goto

      Oracle uses work areas to execute SQL statements and store processing information. A 
      PL/SQL cursor is a construct that lets you name a work area and access its stored information. There are two kinds of cursors: implicit and explicit. PL/SQL implicitly declares a cursor for all SQL data manipulation statements, including queries that return only one row. For queries that return more than one row, you can explicitly declare a cursor to process the rows individually. For example (taken from Oracle docs):

      DECLARE
         CURSOR c1 IS
            SELECT empno, ename, job FROM emp WHERE deptno = 20;
          ...
      BEGIN
         FOR emp_rec IN c1 LOOP
            ...
            salary_total :=  salary_total + emp_rec.sal;
         END LOOP;
      The query returns a result set and the cursor allows you to process one row at the time.
       
       
      
      

      Data Warehousing Concepts

      A data warehouse is a non-volatile copy of data that is usually also subject-oriented, time-variant, and integrated from multiple data sources.
      • non-volatile: Once the data is in the warehouse it will not be modified or deleted
      • subject-oriented: The data is usually designed to facilitate analysis and reporting for a particular subject area (eg: sales)
      • time-variant:Historical data is stored, as opposed to just the latest relevant transaction
      • integrated: Data from multiple sources is merged into the warehouse

      Thursday, July 1, 2010

      Spring Overview

      Spring is an open source framework created to address the complexity of enterprise application development and promote good programming practices. It does this by enabling a POJO-based programming model that is applicable in a wide range of environemnts.

      Spring has a layered architecture so almost any part of it can be used in isolation. For example, Spring may be used just to simplify use of JDBC.

      It consists of the following 7 modules:
      1. Core container module - provides the IoC features
      2. Application context module -
      3. AOP module - provides an AOP implementation
      4. ORM module - provides integration layers for popular OR mapping APIs (eg: JPA, JDO, Hibernate)
      5. DAO module - provides a JDBC abstraction layer
      6. Web module - provides basic web-oriented integration features
      7. MVC framework - provides a MVC implementation for web applications
      The Spring BeanFactory, the foundation of Spring as an IOC container, is a generic factory that enables configured objects to be retrieved by name, and which can manage relationships between objects.

      The ApplicationContext builds on top of the BeanFactory and adds other functionality, such as easier integration with AOP features, message resource handling, event propagation, etc.

      Struts Overview

      Struts is an open-source web application framework for developing servlet/JSP based applications. It concentrates on the web tier, and aside from providing a simple JDBC connection pool, does not attempt to address persistence requirements.

      It does, however, suggest the use of a domain object model and business logic beans, and its tag libraries include a number of tags for working with JavaBeans.

      The Struts framework provides 3 key components:
      • A request handler provided by the application developer that is mapped to a standard URI.
      • A response handler that transfers control to another resource which completes the response.
      • A tag library that helps developers create interactive form-based applications with server pages.
      Struts applications have 3 major components:
      • A servlet controller, which is provided by Struts
      • JSP pages (the view)
      • The application's business logic (the model)

      Wednesday, June 30, 2010

      DOM

      The DOM is a programmable representation of a document or web page. While we see each page as a visual construct, the browser recognises it as a tree structure of elements and properties. In the DOM, every part of the document is a note, which is text, and element, an attribute, etc. The DOM provides methods to reach all these notes and to add, remove, and modify them.

      DOM scripting therefore refers to programatically accessing the DOM. In common usage, DOM scripting implies JavaScript.

      The advantages/features of the DOM model include:
      • progressive enhancement (ie: enhancing the page increasingly with the support of the client, as opposed to graceful degradation)
      • separation of presentation and behaviour
      • maintainability
      • separation of structure and behaviour
      • event handling

      Advantages and Disadvantages of Javascript

      Created by Netscape in 1996, JavaScript has little to do with Java (confusing as the naming is) except for the fact that some of the syntax looks similar. Javascript is a browser-based programming language that runs client-side.

      Advantages:
      • Enables data validation on the client side resulting in a smoother user experience and less load on the server
      • It is supported by most browsers due to its popularity. No extra downloads are required to view JavaScript
      • It does not require any special compilers or editors
      • JavaScript excels in the creation of dynamic effects (eg: rollover images)
      • JavaScript load time is faster than some other front-end technologies (eg: Flash, Java Applets)
      Disadvantages:
      • Not all browsers support JavaScript consistently and to the same version.
      • If JavaScript is not stored separately it makes it difficult for search engine crawlers to find keywords and content in web pages.

      Advantages of JSP

       JSP is a Java-based technology for creating dynamic web pages.

      The following are some of the disadvantages of client-side scripting compared to JSP:
      • The user's browser must have scripting enabled, which is not always the case
      • The client-side code can only  be guaranteed to work for all the brower types it has been tested against. It can be a pain to code for multiple browsers
      • Client-side scripts have limited access to server-side resources (eg: databases)
      • Client-side scripting languages are less versatile than Java.
      Some of the advantages of JSP over client-side scripting are as follows:
      • JSP enables clean separation of business logic from presentation
      • JSP is not limited to a specific platform, being Java-based and compiled into bytecode.
      • As JSP pages execute on the server it does not matter what browser or configuration the client has.
      • JSP has full access to server-side resources.
      For all intents and purposes JSP is a sohpisticated Java Servlet. The main advantage of JSP over Java Servlets is the ease of coding - static text is achieved using HTML tags as opposed to a multitude of println statements.

      Tuesday, June 29, 2010

      Simple EJB3 Example

      This post provides instructions on creating a simple Stateless Session Bean and a test client to see it working. It assumes Eclipase IDE and JBoss.

      Create a new EJB project in Eclipse, called EJB3SessionBeanExample. Accept all project defaults.

      Create 2 packages under the ejbModule directory: "bean" and "client"

      Create the following classes under the bean folder:

      IHelloBean

      package bean;

      import java.io.Serializable;

      public interface IHelloBean extends Serializable {
        public void doSomething();
      }

      HelloBeanRemote

      package bean;
      import javax.ejb.Remote;

      @Remote
      public interface HelloBeanRemote extends IHelloBean {

      }

      HelloBeanLocal

      package bean;
      import javax.ejb.Local;

      @Local
      public interface HelloBeanLocal extends IHelloBean {

      }

      HelloBean

      package bean;

      import javax.ejb.Stateless;

      /**
      * Session Bean implementation class
      */
      @Stateless
      public class HelloBean implements HelloBeanRemote, HelloBeanLocal {

        private static final long serialVersionUID = 9184424076718418234L;
        public void doSomething() {
          System.out.println("Hello World!");
        }
      }

      Create the HelloBeanClient under the client folder:

      package client;

      import java.util.Properties;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;

      public class HelloBeanClient {
        public static void main(String[] args) {
          try {
            Properties props = new Properties();
            props.setProperty("java.naming.factory.initial",
                "org.jnp.interfaces.NamingContextFactory");
            props.setProperty("java.naming.factory.url.pkgs",           "org.jboss.naming");
            props.setProperty("java.naming.provider.url",
      "127.0.0.1:1099");

            InitialContext ctx = new InitialContext(props);
            MyBeanRemote bean = (MyBeanRemote) ctx.lookup("MyBean/remote");

            bean.doSomething();
          } catch (NamingException e) {
            e.printStackTrace();
          }
        }
      }

      Right click on the EJB3SessionBeanExample project and select Run As -> Run on Server to publish to the server.

      Once it is successfully deployed, right click on the HelloBeanClient class and select Run As -> Java Application. Accept any defaults and run it. You should see Hello World! printed to the console (or log C:\Apps\JBoss\jboss-5.1.0.GA\server\default\log depending on setup).

      Simple JSP Example

      The following post provides an example of a simple JSP page and instructions on how to deploy and view it. It assumes the use of Eclipse and JBoss.

      Create a new Dynamic Web Project in Eclipse called HelloWorld.You can accept the defaults, such as "WebContent" for the web root.

      Create the file HelloWorld.jsp under the WebContent directory and paste the following code in:

      <%@ page language="java" %>
      <html>
      <body>
      <%
        for (int counter = 1; counter <= 10; counter++) {
      %>
          Hello World!<br>
      <%
        }
      %>
      </body>
      </html>

      Create a file called web.xml under the WEB-INF directory (which should have been automatically created under the WebContent directory) and paste in the following:

      <?xml version="1.0" encoding="ISO-8859-1"?>
      <!DOCTYPE web-app
          PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
          "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
      <web-app>
      </web-app>


      Right-click the HelloWorld project folder and select Run As -&gt; Run on Server. Accept any defaults and run it on your local server. This should put a war file in C:\Apps\JBoss\jboss-5.1.0.GA\server\default\deploy (or equivalent).

      Now go to http://localhost:8080/HelloWorld/HelloWorld.jsp and you should see:

      Hello World!
      Hello World!
      Hello World!
      Hello World!
      Hello World!
      Hello World!
      Hello World!
      Hello World!
      Hello World!
      Hello World!

      Simple.

      Thursday, June 24, 2010

      Retarded IE javascript error messages

      Error: Expected ';'
      Code: 0

      Could well mean that you have capitalised the first letter of a variable declaration (Var instead of var) in error, as javascript is case-sensitive, and IE is retarded.

      Tuesday, June 22, 2010

      Perhaps JAVA_HOME does not point to the JDK...

      Buildfile: C:\dev\EJB3Tutorial\EJB3JSPExample\ejbModule\build.xml
      init:
      build:
      [javac] Compiling 2 source files to C:\dev\EJB3Tutorial\EJB3JSPExample\ejbModule\build\classes

      BUILD FAILED
      C:\dev\EJB3Tutorial\EJB3JSPExample\ejbModule\build.xml:41: Unable to find a javac compiler;
      com.sun.tools.javac.Main is not on the classpath.
      Perhaps JAVA_HOME does not point to the JDK.
      It is currently set to "C:\Program Files\Java\jre6"

      Total time: 219 milliseconds

      A solution to this in Eclipse is to edit Ant's runtime properties (Window > Preferences > Ant > Runtime). Select the Global Properties node in the Classpath tab and click Add External Jars. Select tools.jar from your JDK directory (e.g., C:\Program Files\Java\jdk1.6.0_20\lib\tools.jar).

      EJB Web Service Frustrations

      It always amazes me how much time can be wasted trying to get some simple framework/middleware up and running. There is no actual coding involved, only googling error messages, substituting various pieces, plugging, patching, copying and pasting, etc, etc. And sadly today I am no where near as close to getting EJB3 web services working as I would like.

      I wanted to get this working as there are a number of advantages to using EJBs as web services instead of POJOs:
      • A richer set of protocols are available
      • Gain access to framework like declarative security and transactions

      So I began by googling to find a simple example that I could copy and paste into a few beans/classes and see some results without too much hassle. This was not a problem and I'd created a Remote Interface @WebService using @SOAPBinding(style=Style.RPC), declaring a couple of @WebMethod s, a stateless session bean implementing those methods, and a Client to test it within 10 minutes.

      And then the fun began. It deployed with no problems but when I ran the client it crashed with some error about not being able to find some Xerces class. I googled that message and soon figured out that for some reason JBoss was not looking at the .../lib/endorsed/ folder where xercesImpl.jar was. Neither could I figure out how to make it look there so I just added the xercesImpl.jar as an external library. And that fixed that.

      Running the client once more resulted in:

      Exception in thread "main" java.lang.reflect.UndeclaredThrowableException at $Proxy0.add(Unknown Source) at org.jboss.tutorial.webservice.client.Client.main(Client.java:45)Caused by: java.rmi.RemoteException: Call invocation failed; nested exception is: java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage at org.jboss.ws.core.jaxrpc.client.CallImpl.invokeInternal(CallImpl.java:535) at org.jboss.ws.core.jaxrpc.client.CallImpl.invoke(CallImpl.java:275) at org.jboss.ws.core.jaxrpc.client.PortProxy.invoke(PortProxy.java:154) ... 2 moreCaused by: java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage at javax.xml.soap.SOAPMessage.setProperty(Unknown Source) at org.jboss.ws.core.soap.SOAPMessageImpl.(SOAPMessageImpl.java:87) at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:169) at org.jboss.ws.core.CommonSOAP11Binding.createMessage(CommonSOAP11Binding.java:57) at org.jboss.ws.core.CommonSOAPBinding.bindRequestMessage(CommonSOAPBinding.java:157) at org.jboss.ws.core.CommonClient.invoke(CommonClient.java:290) at org.jboss.ws.core.jaxrpc.client.CallImpl.invokeInternal(CallImpl.java:516) ... 4 more

      This after much googling I concluded to be a SOAPMessage implementation bug, where the setProperty() method has been overridden in the abstract SOAPMessage class instead of the SOAPMessageImpl subclass where it should have been. The SOAPMessageImpl class is being loaded from rt.jar (Java 1.6) in the classpath instead of the JBoss one, and it calls the setProperty() method of the parent, which throws the UnsupportedOperationException. Hmmm... I'm not even sure if that makes sense as I have not looked into the source of the implementations but taken the explaination from another site. Note to self, check this.

      I then proceeded to attempt to make JBoss look at the right jars by placing jbossws-native-core.jar and various other jbossws jars in the /lib/endorsed directory, adding them as external jars directly, and even taking some users' suggestions and using Java 5 instead of 6. Sadly none of this worked for me and I by the time I have given up for the day and set about documenting my experiences I have worked almost an 8 hour day (with liberal breaks for morning tea, lunch, a run, and a shower). I am no Eclipse guru and just switching to Java 5 took enough time by the time I figured out that I should really set the version of Java via the Project Properties -> Project Facets panel to make it take effect on the "java facet" version as well as the compiler compliance level. If it isn't set here the following error results:

      "Java compiler level does not match the version of the installed Java project facet"

      So a whole day has gone by and I have not managed to get a simple EJB3 web service example working. This is one thing that continues to frustrate me about software development - the amount of wasted time spent googling errors and trying random fixes in order to get something so simple working. Hopefully my next post will be an update on how I finally got a simple EJB3 web service working!

      Software Design Patterns - Overview and Rant

      General reusable solutions to commonly occurring problems in software design, made popular by the 1994 book by the "Gang of four". Lately I am leaning towards dismissing them as buzz-words that wanna-be l33t hax0rs use to impress/confuse and a favourite question of interviewers. More and more patterns that I come across in reading seem to be post-hoc descriptions of designs that I or other developers have used frequently without attributing a spiffy name to. For example, the Strategy pattern - a design pattern whereby algorithms can be selected at runtime, implemented using concrete strategy classes implementing a strategy interface. How is that different from polymorphism? If anything it is a subset of polymorphism and adds nothing new. And the Iterator pattern??

      I admit I do find some pattern identification useful. For example, the Facade - exactly what it sounds like, defines a higher-level interface that makes a subsystem easier to use.

      Although the Singleton is still often identified as a pattern, there is growing belief that it should really be classed as an anti-pattern. Some of the drawbacks identified include the following:
      • The limitations it introduces may be unnecessary, ie: a sole instance may not actually be required in a given situation. Additionally these limitations may cause threading issues.
      • Singletons introduce global state into applications resulting in dependencies in the design being hidden inside the code, rather than obvious dependencies highlighted by method parameters for example.
      • For purists, Singletons mix two different responsibilities in the same class, one of them being the control over the number of instances of itself. This may be better handled using a Factory to encapsulate creation and limit instances.
      In short, although I think the study of design patterns (and anti-patterns) is great for building up a budding developer's abilities, I am somewhat sceptical about 1) the introduction of new terminology to describe existing simple solutions to a problem, that really don't require another name, and 2) the proliferation of patterns in areas where something simpler and more customised would be a lot easier to understand and maintain.
       
      Powered by Blogger