Monday, January 17, 2011

Injecting ExtJS components via an html template

Use Ajax to load an html page as a template for ExtJS and then plug ExtJS components into it.

Sometimes a web page layout may be too complicated or time-consuming to develop purely in ExtJS or perhaps you want to convert an existing html page to use ExtJS components. In either case there is a simple and straightforward way to inject ExtJS components into a complex html page. There are only a few simple steps needed to accomplish this:
  • create the html
  • fetch the html
  • load the html
  • plug in the ExtJS components
Here is a snippet from myPage.html. Notice the {idBase} included as part of the id. That is a template param that will be replaced when the ExtJS XTemplate is processed. The purpose of {idBase} is to help make sure that each div section has a unique ID and is not really germain to this article.
    
...
The following methods are from myScript.js. This method loads the html using an Ajax request:
     initStructure : function() {
         Ext.Ajax.request({
             url : 'myPage.html',
             disableCaching : false,
             method : 'GET',
             success : this.onStructureLoaded.createDelegate(this)
         });
     } // initStructure()
This success handler puts the html text into an ExtJS XTemplate and then loads that into the body of this component (an ExtJS panel or window):
     onStructureLoaded : function(response, options) {
         var template = new Ext.XTemplate(
             response.responseText
         });

         this.body.update(template.apply({
             idBase : this.id
         }));

         this.initMyButton();
     ...
     } // onStructureLoaded()
Once the html has been loaded into the DOM we can start plugging our ExtJS components into it:
     initMyButton : function() {
         new Ext.Button({
             applyTo : this.getCustomId('myButton'),
             text : 'My Button',
             handler : this.onMyButtonClick.createDelegate(this)
         });
     } // initMyButton()

     getCustomId : function(name) {
         return String.format('{0}_{1}', name, this.id);
     } // getCustomId()

Wednesday, January 12, 2011

Spring-loading and injecting external properties into beans

Let's say you have a Spring managed bean that contains some properties that you would like to externalize from your application, say perhaps in a JBoss 'conf' folder properties file.  Apparently you can do this via annotations in Spring 3, but it's also fairly straightforward in Spring 2.5:

From the context.xml file:

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:my_app.properties"/>
        <property name="placeholderPrefix" value="$prop{"/>
    </bean>
 
    <bean id="someBeanWithProps" class="my.class.with.Props">
        <property name="myPropA" value="$prop{prop.file.entry.prop.A}"/>
        <property name="myPropB" value="$prop{prop.file.entry.prop.B}"/>
    </bean>

JBoss, JNDI and java:comp/env

On startup JBoss will process any xyz-service.xml files it finds in the deploy folder before it processes any war or ear files, etc.  One thing this could be useful for is to preload configuration values into JNDI, thus making them available to web applications when they start up.  It may sound simple but it consists of a non-obvious four step process:

1.  Create a JNDIBindingServiceMgr mbean in the xzy-service.xml file.

2.  In the WEB-INF/jboss-web.xml file map a resource-env-ref entry over to a JNDI value bound in step 1.

3.  In the WEB-INF/web.xml file create a resource-env-ref entry for each JNDI bound value.

4.  Access the JNDI value from somewhere, such as a servlet filter, using 'java:comp/env'

First, the xyz-service.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE server PUBLIC "-//JBoss//DTD MBean Service 4.0//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-service_4_0.dtd">
<server>

    <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
           name="netcds.cas.client:service=JNDIBindingServiceMgr">

        <attribute name="BindingsConfig" serialDataType="jbxb">

            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">

                <jndi:binding name="my/jndi/property">
                    <jndi:value type="java.lang.Boolean">false</jndi:value>
                </jndi:binding>

            </jndi:bindings>
        </attribute>
        <depends>jboss:service=Naming</depends>
    </mbean>

</server>

Next, the resource-env-ref entry in the jboss-web.xml file:

    <resource-env-ref>
        <resource-env-ref-name>my/jndi/property</resource-env-ref-name>
        <jndi-name>my/jndi/property</jndi-name>
    </resource-env-ref>

And the associated web.xml entry:

    <resource-env-ref>
        <resource-env-ref-name>my/jndi/property</resource-env-ref-name>
        <resource-env-ref-type>java.lang.Boolean</resource-env-ref-type>
    </resource-env-ref>

Finally, accessing the JNDI value from a servlet filter:
      
    boolean result = false;
    try {
        InitialContext context = new InitialContext();
        result = (Boolean)context.lookup("java:comp/env/my/jndi/property");
    } catch (final NamingException e) {
        // log and/or sys out
    }