Chris' SWI blog

http://blogs.sun.com/chrisf/date/20080812 Tuesday August 12, 2008

JSF - making sure your JSF pages load prior to calling JavaScript methods

Here's a quick note, but I found it very useful when it came to testing FireFox 3 and/or IE 8:

<![CDATA[
  function OnLoad() {
    var ignoreMe = document.body.offsetWidth;

    if (ignoreMe == null) {
       return setTimeout('OnLoad();', 10);
    }

    parent.leftFrame.location.href = "/faces/NavigationPage.jsp";
  }
]]>

Then I add the javascript onLoad method to the JSF body tag (onLoad="OnLoad()") for example:

<webuijsf:body binding="#{com$FirstPage.body1}" id="body1" onLoad="OnLoad();" style="-rave-layout: grid">

That's it, this simple onLoad event makes sure the document has a page width set, if it doesn't I use the timeout method to re-call the OnLoad event and try again.

http://blogs.sun.com/chrisf/date/20080729 Tuesday July 29, 2008

NetBeans 6.1: Fixing the insertion of JSR-311 files in to the JSF/Web Application project randomly.

Howdy Folks, just thought I would share an FYI for you all...

Recently I faced this issue with my project: http://forums.java.net/jive/thread.jspa?threadID=40113

I experienced this issue myself recently; NetBeans 6.1. GlassFish v2ur2

The particulars:

Product Version: NetBeans IDE 6.1 (Build 200804211638)
Java: 1.6.0_05; Java HotSpot(TM) 64-Bit Server VM 1.6.0_05-b13-52
System: Mac OS X version 10.5.3 running on x86_64; MacRoman; en_US (nb)

I followed the instructions in that blog/forum to remove the following entries in the web.xml and removed the line, com.sun.ws.spi.container.servlet.ServletContainer and references to RESTFul Web Services

I have since updated my NetBeans install and updated the recent Jersey plugin to 0.8. On a NetBeans 6.1 restart, I then saw all of these Jersey API's loaded as part of my project and a few lines added to my build-impl.xml which in turn seems to add all of these API's to my project, for example the new build sub-file being imported in to my project <import file="rest-build.xml"/>. I'm not using REST in my Project so I didn't want to add all of those unnecessary libraries.

So to sumarise, make sure you remove all entries to REST in your project, in my case this meant that I needed to remove the import rest instructions as well.

I hope this helps others facing a similar issue.

http://blogs.sun.com/chrisf/date/20080725 Friday July 25, 2008

OpenSolaris 2008.05 - Performing a package update/upgrade

Howdy Folks, I thought I would share this tid-bit of information that saved me lots of time (and pain).

I tried installing Open Solaris 2008.05 on to my MAC Laptop using VirtualBox 1.6.2. All went very well, the install was easy, clicked to install the Live CD and followed the step-by-step wizard to install the product.

I then thought, OK, what other packages are available, what products / patches are there that I can install... So I did a "Install All", I was logging in as chrisf/password.

All went ok, it started to download 3GB's of data and after a few long hours -- like watching the grass grow -- it was ready to install. It started ticking away got to about 5% of the way through the progress then seemed to hang. No errors in any log, no errors in the console, I was stuck. Luckily I made a back-up/snapsot using virtual box...

I then rolled back to the good working snapshot... Like all good ol' techies I tried again, but was going to work out what the problem might be.

Instead of using the "Menu" System->Administration and selecting Package Manager, I decided to try a few things from command line.

gksu /usr/bin/packagemanager

I then tried the same thing... thinking something may be different when running as root.

I watched the grass grow -- and had a similar experience the install seemed to hang (AGAIN after the 3gig download).

HOWEVER in the terminal window was an error, ah-huh... perhaps a package install failed...

The error occured with SUNWslim-utils a user was not found on the system... ah huh...

OK, so I then reverted to the snapshot again, thought third time is a charm and tried again, again from command line... I selected ALL but this particular package and after the 3 gig download, I was actually able to get all of the packages installed :-)

Rule of Thump, use the command line version :-)

http://blogs.sun.com/chrisf/date/20080717 Thursday July 17, 2008

Retrieving JSF Session variables in your servlets

Quite often in your JSF Application you need to call a backend servlet to perform a certain task. Perhaps in the back-end servlet you may want would also need to retrieve a variable out of the JSF's SessionBean1 properties.

Here's a quick capture showing you how to retrieve a variable out of JSF's SessionBean1 object.

Create the following global variables for your servlet class:

private ServletContext context;
private Lifecycle lifecycle;
private ServletConfig servletConfig;
private FacesContextFactory facesContextFactory;
private FacesContext facesContext;

In your servlets init(...) method add the following snippets of code:

this.servletConfig = config;
this.context = config.getServletContext();

Then capture and retrieve the faces context:

try {
facesContextFactory =
(FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
} catch (FacesException e) {
Throwable rootCause = e.getCause();

if (rootCause == null) {
throw e;
} else {
throw new ServletException(e.getMessage(), rootCause);
}
}

try {
LifecycleFactory lifecycleFactory =
(LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
String lifecycleId =
servletConfig.getServletContext().getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);

if (lifecycleId == null) {
lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
}

lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
} catch (FacesException e) {
Throwable rootCause = e.getCause();
if (rootCause == null) {
throw e;
} else {
throw new ServletException(e.getMessage(), rootCause);
}
}

Add the following code to your destroy() method:


facesContextFactory = null;
lifecycle = null;
servletConfig = null;
context = null;
facesContext = null;

Lastly, add the following methods to your servlet class to retrieve your chosen variables out of the SessionBean1 object (your JSF Session Variables):

/** Evaluate and return the given value binding expression
* @param context The FacesContext for this web app
* @param expr The value binding expression to be evaluated, such as "Sum is #{foo.sum}"
* @return The value of the expression
*/
private Object getValue(FacesContext context, String expr) {
return getValue(context, expr, expr.getClass());
}

protected Object getValue(FacesContext context, String expr, Class c) {
ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(
context.getELContext(), expr, c);

if (ve != null) {
return ve.getValue(context.getELContext());
}

return null;
}

/** Evaluate and return the given value binding expression
* @param context The FacesContext for this web app
* @param expr The value binding expression to be evaluated, such as "Sum is #{foo.sum}"
* @return The value of the expression
*/
protected void setValue(FacesContext context, String expr, String value) {
ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(
context.getELContext(), expr, value.getClass());

if (ve != null) {
ve.setValue(context.getELContext(), value);
}
}

/** Find the named JSF managed bean
* @param context The FacesContext for this web app
* @param expr The name of the managed bean to be found, such as "SessionBean1"
* @return The managed bean
*/
protected Object getBean(FacesContext context, String name) {
ELResolver resolver = context.getApplication().getELResolver();

return resolver.getValue(context.getELContext(), null, name);
}

Then in your doGet or doPost method(s) add:

// Acquire the FacesContext instance for this request
facesContext = facesContextFactory.getFacesContext(servletConfig.getServletContext(), request, response, lifecycle);

Now for the fun part;

To retrieve a variable out of the SessionBean class say, name, you can use the following snippet of code:

String name = (String) getValue(facesContext, "#{SessionBean1.name}");

You can also update your JSF session variables as well via the following snippet of code:

setValue(facesContext, "#{SessionBean1.name}", name.toString());

Wella, Done!

http://blogs.sun.com/chrisf/date/20080625 Wednesday June 25, 2008

JSF: Speeding up delivery of JSF pages to the client/browser using http compression and a caching filter

Howdy folks, well I thought I would share / combine a few of the techniques I found a month or two ago that I now use to speed up the delivery of JSF pages to the client. Leveraging caching of images/css and javascript objects and enabling HTTP 1.1 compression...A thanks goes out to Jean-Francois Arcand, lowec and Rafael Pereyra

Products involved:

  • GlassFish v2ur2
  • NetBeans 6.1
  • Visual JSF: 1.0.4
  • The steps involved:

  • Create a Filter to cache the following objects; *.png, *.css, *.js, *.gif, *.jpg, see forum posting here under heading Re: Creator and cache Jun 7, 2006 6:41 AM (reply 6 of 7)
  • Turn on HTTP 1.1 compression for GlassFish referencing Jean-Francois Arcand's Blog.
  • Thats all, doing so I was able to gain much faster client/server responses and improve the overall user experience.

    The only issue I have experienced doing so, was that every now and again I had to clean out my browser cache when I was testing a modified page.

    June 25th 2008 Update

    Since using the above technique to speed up delivery I noticed that there were a few issues with the "back" button in Internet Explorer and Safari browsers. I have now gone down the path of intoducing a phace listener in to the JSF framework; making sure that each page is not cached so that the page will be refreshed by the system. The phase listener was I found courtesy of http://turbomanage.wordpress.com/2006/08/08/disable-browser-caching-in-jsf/. I have updated the phase listener presented here slightly to introduce another meta tag, "EXPIRES" I set this to current date minus a year to make sure the systemrefreshes the content.

    The performance gain I was getting chaching pages hasn't actually hindered that much as all. When woodstock 4.2 was released, many performance improvements were seen, for more information see: http://www.nabble.com/Woodstock-4.2-Performance-tc15884700.html

    • GlassFish v2ur2
    • NetBeans 6.1
    • Visual JSF: 1.1.1

    Try out both ideas, se which one works better for you, let me know what you think.

    Cheerio!

     

    http://blogs.sun.com/chrisf/date/20080527 Tuesday May 27, 2008

    Yet another successful eHorizons event in Sydney, Australia

    Over the past three days; Sunday through to Tuesday, Sun Microsystems Australia and New Zealand hosted in Sydney a Sun Software user conference, covering topics such as MySQL, Identity Management, Java CAPS and the Middleware stack from Sun Microsystems, such as GlassFish, Open Portal, OpenSSO etc. See http://au.sun.com/sunnews/events/2008/horizons/ for more information

    There was plenty of buzz around the conference floor, many water-cooler chats, war stories and all round lots of fun for all that attended.

    I presented on the following three topics:

  • Application Server 9.1 Tuning
  • Enterprise Infrastructure Platform Roadmap and Highlights
  • Developer Tools Update: NetBeans and Family
  • Click on any of the above three links to download my presentation. Feel free to leave a comment or email me for any thoughts, suggestions or assistance that you may require. All of the other presentations will be available for download shortly, be sure to check out the horizons URL above.

    I hope to see you all next year!

    Cheerio,

    Chris

    http://blogs.sun.com/chrisf/date/20080502 Friday May 02, 2008

    Visual Web Pack: Using radio buttons to select and deselect your tabs from the TAB Pane

    Firstly the tools/products involved:

  • NetBeans IDE 6.0 (Build 200711261600)
  • Visual JSF, version: 1.0.3
  • GlassFish v2, update release 1
  • I thought I would share my experiences with the community on how I was able to toggle tab-panes on and off with a checkbox. Please let me know if you have an easier or better way. :-) Say you have two tab's, one that you want to toggle on or off, and another that remains enabled.

    Step 1: Make the check-box auto submit on change. Make sure the check-box starts of as selected="true", "selectedValue=true", and the immediate flag is selected.

    Step 2: Create a virtual form for the check-box, making sure it submits and participates in the virtual form created.

    Step 3: Add a hidden field to the form for use in the Java code (hiddenField1)

    Step 4: Add a SessionBean (SessionBean1) property to store the check-box state. Add get and set methods for the property.

    private boolean checkBoxSelected = true;

    public boolean isCheckBoxSelected() {
        return checkBoxSelected;
    }

    public void setCheckBoxSelected(boolean checkBoxSelected) {
        this.checkBoxSelected = checkBoxSelected;
    }

    Step 5: Double-click the check-box to add a valueChange method. Add the following code to the valueChange method:

    if (checkbox1.isChecked() == true) {
        tab2.setStyle("visibility: visible");
        hiddenField1.setText("true");
    } else {
        tabSet1.setSelected("tab1");
        tab2.setStyle("visibility: hidden");
        hiddenField1.setText("false");
    }

    The above code checks whether the check-box was select and enables Tab2 (in this case the second tab) if true (i.e. the check-box was ticked) and if false (un-ticked) the tab selected is set to "tab1" - the tab thats always enaled and we then disable the second tab chaning the visibility attribute, "visibility: hidden".

    Step 6: Add the following code to the prerender method:

    String selected = (String)hiddenField1.getText();

    if ((selected != null) && (selected.equals("true"))) {
        getSessionBean1().checkBoxSelected(true);
    } else if (selected == null) {
        checkbox1.setSelected(new Boolean(getSessionBean1().checkBoxSelected()));
    } else
        getSessionBean1().checkBoxSelected(false);
    }

    if (checkbox1.isChecked()) {
        tab2.setStyle("visibility: visible");
    } else {
        tab2.setStyle("visibility: hidden");
    }

     

    My second experience I would like to share with you is;

    Using multiple check-boxes (in this case 2 check-boxes) with the multiple tab-panes (in this case 2) to toggle either tabpane on or off. For example, selecting check-box 1 enables tab-pane 1, selecting check-box 2, enables panel 2. In this particular situation however, I want to make sure that at least one check-box is selected (thus one tab at a miminum is shown). The reason for using the Session Bean is to make sure that on the page reload, the check-boxes are set accordingly to what was previously selected and the respective tab enabled or disabled.

    Step 1: Make box check-boxes auto submit on change. Make sure both check-boxes starts of as selected="true", "selectedValue=true", and the immediate flag is selected.

    Step 2: Create a virtual form for both check-boxes, making sure they are submitting and participating in the virtual form created.

    Step 3: Add two hidden fields to the form for use in the Java code (hiddenField1 and hiddenField2)

    Step 4: Add two SessionBean (SessionBean1) properties to store the check-box statse. Add get and set methods for the property.

    private boolean checkBoxSelected1 = true;

    public boolean isCheckBoxSelected1() {
        return checkBoxSelected1;
    }

    public void setCheckBoxSelected1(boolean checkBoxSelected1) {
        this.checkBoxSelected1 = checkBoxSelected1;
    }

    private boolean checkBoxSelected2 = true;

    public boolean isCheckBoxSelected2() {
        return checkBoxSelected2
    }

    public void setCheckBoxSelected2(boolean checkBoxSelected2) {
        this.checkBoxSelected2 = checkBoxSelected2;
    }

    Step 5: Double-click the check-boxes to add a valueChange method for each check-box and add the following code to the valueChange methods:

    For Check Box 1:

    if (checkbox1.isChecked() == true) {
        tab1.setStyle("visibility: visible");
        hiddenField1.setText("true");
    } else if (checkbox2.isChecked() == true) {
        tabSet1.setSelected("tab2");
        tab1.setStyle("visibility: hidden");
        hiddenField1.setText("false");
    } else {
        tab1.setStyle("visibility: visible");
        checkbox1.setSelected(true);
        hiddenField1.setText("true");
    }

    As you will see frm the code above, it checks whether check-box 1 is selected, if so it enables tab 1. Otherwise it's not meant to be enabled, but based on my use case one tab (of 2) needs to be enabled so it checks check-box 2 to see whether it has been selected or not. if check-box 1 is not selected but check-box 2 is, it disables tab 1 and enables tab 2... if both check-box 1 and 2 aren't selected (not checked), it keeps tab 1 enabled, and checkbox 1.

    For Check Box 2:

    if (checkbox2.isChecked() == true) {
        tab2.setStyle("visibility: visible");
        hiddenField2.setText("true");
    } else if (checkbox1.isChecked() == true) {
        tabSet1.setSelected("tab1");
        tab2.setStyle("visibility: hidden");
        hiddenField2.setText("false");
    } else {
        tab2.setStyle("visibility: visible");
        checkbox2.setSelected(true);
        hiddenField2.setText("true");
    }

    The code for check-box 2 imilarly does what the code I wrote above for check-box 1 only in reverse - tab 2 not tab 1.

    Step 6: Add the following code to the prerender method:

    String selected = (String)hiddenField1.getText();

    if ((selected != null) && (selected.equals("true"))) {
        getSessionBean1().checkBoxSelected1(true);
    } else if (selected == null) {
        checkbox1.setSelected(new Boolean(getSessionBean1().checkBoxSelected1()));
    } else {
        getSessionBean1().checkBoxSelected1(false);
    }

    if (checkbox1.isChecked()) {
        tab1.setStyle("visibility: visible");
    } else {
        tab1.setStyle("visibility: hidden");
    }

    selected = (String)hiddenField2.getText();

    if ((selected != null) && (selected.equals("true"))) {
        getSessionBean1().checkBoxSelected2(true);
    } else if (selected == null) {
        checkbox2.setSelected(new Boolean(getSessionBean1().checkBoxSelected2()));
    } else {
        getSessionBean1().checkBoxSelected2(false);
    }


    if (checkbox2.isChecked()) {
        tab2.setStyle("visibility: visible");
    } else {
        tab2.setStyle("visibility: hidden");
    }

    Please let me know what you think! Comments are welcome!

    http://blogs.sun.com/chrisf/date/20080409 Wednesday April 09, 2008

    A GlassFish adopter in Australia

    Reino International, a division of Saltbush Parking Services, is the largest paid parking equipment and service provider in Australasia and the USA.

    Reino designs and manufactures parking meters, enforcement technologies and the management systems used to manage and enforce on-street and off-street

    Reino decided to use GlassFish for its web-based reporting application. GlassFish at the time was the only product that supported Java EE 5 technologies (JSF, JAX-WS and JPA). The System has now been place for over 18 months, see their story here Reino Develops a Web Based Reporting Application

    http://blogs.sun.com/chrisf/date/20080402 Wednesday April 02, 2008

    GlassFish v2: Changing JVM Options in a Cluster Config - make sure you start the instances properly

    I recently came across an issue where I had to set particular jvm options like; the system classpath, the javaagent, a log4j reference etc.

    When starting the node-agent with the default operation of starting the listening instances (instances syncing with that particular node-agent) asadmin start-node-agent NODE-AGENT-NAME I was seeing that the newly inputted configurations were not getting synchronized with the cluster-configuration changes.

    After discussing with engineering I found out it was a known problem with the start-up sequence and that the workaround was to start the node-agent without the instances starting as well. Then after a successful node agent start I would/can then start the cluster (the instances).

    The commands I used to do this was/were:
    1) asadmin start-node-agent --startinstances=false NODE-AGENT-NAME
    2) asadmin start-cluster CLUSTER-NAME

    After following these two steps above as oppose to the default node-agent start fixed the issue. I got my JVM settings down to the instances... I also wrote a wiki entry on this issue here http://wiki.glassfish.java.net/Wiki.jsp?page=JVMOptions

    http://blogs.sun.com/chrisf/date/20080326 Wednesday March 26, 2008

    My first entry/blog on blogs.sun.com: Comparing GlassFish v2 to Geronimo v2.0.0

    Recently I did a comparison of two open source products, Sun's GlassFish project VS IBM's Geronimo project. Here are 12 bullet points for your consideration. There are a few standout features in favour of GlassFish over Geronimo, these include:

    1/ To download Geronimo you need to log in and leave behind your reasons for the download; "still looking", evaluating etc. etc. GlassFish does not ask for such details when downloading...

    2/ Support for the up-most / latest standards in GlassFish compared to Geronimo, for example: The WebSphere Application Server CE 2.0 supports (ships with): XML-Web Services (JAX-WS)/JAX-Binding (JAXB) 2.0, compared to 2.1 in GlassFish.

    3/ In Geronimo to configure virtual hosts, clustering, deployment to clusters you need to use their CLI, GlassFish has a central administration console for this (CLI or GUI console), as mentioned here: virtual-host To deploy an app to a certain virtual host in Geronimo: Deploying an app to a virtual host (again via command line). Compared to: Clustering web applications with GlassFish

    4/ Everything you can do via the administration console, you can do via the CLI, see: Administration console and CLI for more information. [A far more powerful CLI tool than Geronimo has on offer]

    5/ Clustering support is limited in Geronimo, as listed here This feature does not replicate stateful session Enterprise JavaBeans (EJBs). You will need to avoid stateful session EJBs in your distributed applications. This feature does not replicate dynamic updates to the Java Naming and Directory Interface (JNDI). You will need to configure all the JNDI names used by your distributed applications in every node of the cluster. This feature does not replicate distributable web applications to other nodes in the cluster. You will need to deploy your distributable web applications to every node. GlassFish v2 has full clustering support, see wiki entry Clustering can be administered through the GUI Console as listed here (and VIA command line). Applications can also be deployed to a cluster using the GUI console/CLI.

    6/ The Documentation is weak in Geronimo compared to GlassFish, for example the administration guide, see Tuning Java under the Administration section here compared to GlassFish's JVM tuning

    7/ The JVM settings need to be changed from command line (for Geronimo) using "VI" (or your chosen file editor), in GlassFish, you can change these settings through the management console.

    8/ In Geronimo the common libraries area is interesting. The console lists each and every library from different directories (a.k.a. very basic classpath management IMO)

    9/ The admin console for Geronimo, ("http://.:8080/console" ) runs on the same port as the TomcatWebConnector, a.k.a "HTTP" for the Web Server component.

    10/ WebSphere CE 2.0 has limited support for 64bit JVM's (can only use IBM's) see for more information Geronimo's 64bit JVM Support

    11/ GlassFish v2 has call-flow monitoring built in to the admin console for example Call Flow Monitoring in GlassFish and Call Flow Monitoring in GlassFish

    12/ Glassfish has a unique position in the market right now whereby, the same binaries that are released to open-source form Sun's Commercially Supported Application 9.1, see: Productizing Open Source Projects for more information, the only differences being listed here: FAQ GlassFish VS SJSA91 With Geronimo you get to use Java EE 5, but when you need to move to clustering, failover etc. etc. and you move to WebSphere 6.1 you need to make sure your code is 1.4 compliant. The feature packs don't currently cover the full Java EE 5 spec.

    Please don't hesitate to leave comments below and I'll be sure to respond where I can.


    Valid HTML! Valid CSS!

    This is a personal weblog, I do not speak for my employer.