A Sunny Commune - Cheng's Blog

« Previous page | Main | Next page »

http://blogs.sun.com/chengfang/date/20080309 Sunday March 09, 2008

Install JavaEE samples with glassfish updatecenter

This is available in glassfish v2 update release 1 and newer.  Just follow these simple steps to get JavaEE samples, including a quickstart hello webapp:

1, Start glassfish updatecenter

 cd %GLASSFISH_HOME%\updatecenter\bin

updatetool.bat

2, Click "Available Software" tab and then choose "Java EE 5 Samples" in the list of available software

Glassfish updatecenter 

3, Samples are installed at %GLASSFISH_HOME%\samples (Note that this actual location is different from what was documented at the bottom of the above snapshot image.)

C:\glassfish\samples>dir

03/09/2008  05:42 PM    <DIR>          .
03/09/2008  05:42 PM    <DIR>          ..
01/02/2008  11:18 AM            82,562 common-ant.xml
01/02/2008  11:18 AM             1,795 common.properties
01/02/2008  11:18 AM            23,554 GlassFish_LB_Cluster.html
01/02/2008  11:36 AM                28 password.txt
01/02/2008  11:18 AM    <DIR>          quickstart

4, There are currently 2 apps under samples/quickstart: hello.war and clusterjsp.  To deploy hello.war (already built and packaged ready for deployment) using autodeploy, just copy the .war file to %GLASSFISH_HOME%\domains\domain1\autodeploy

5, To run hello webapp, go to the following URL: http://localhost:8080/hello/

Glassfish hello duke

6, To undeploy hello.war, simply delete hello.war from %GLASSFISH_HOME%\domains\domain1\autodeploy

http://blogs.sun.com/chengfang/date/20071225 Tuesday December 25, 2007

Merry Christmas but sorry, no webkinz

Important statement about the content of this post:

I've been informed that Ganz is in fact taking every step possible to ensure they provide their community with an infrastructure that will support the heaviest loads. Sun is in fact working with Ganz to provision this infrastructure, but due to a number of complex reasons the teams were not able to complete the migration prior to the Christmas rush. 

This post is strictly my personal views and does not represent that of my employer or coworkers.  I had underestimated the complexity of managing such a large site.  Some conclusions in this post are premature based on incorrect facts.  My sincere apologies for any hard feelings and hindrance it has caused to webkinz/panther team during this holiday season.  Thank you very much for bringing us this fascinating gift and see you soon at webkinz world. 

Sincerely,

Cheng Fang
 

So today is the Christmas day, a moment kids have been waiting all year long.  After getting a Chihuahua webkinz from Santa this morning, my daughter wasted no time trying to log onto webkinz  to play.  But like millions of kids around the world, she was greeted with this gloomy message on webkinz homepage:

webkinz down

Out of curiosity, I wanted to know what kind of server webkinz is on.  This is what netcraft has to say about this site: 

Netblock OwnerIP addressOSWeb ServerLast changed
Panther Express195.12.231.201LinuxPWS/1.1.2920-Dec-2007
Pather Express213.244.185.11LinuxPWS/1.1.3418-Dec-2007
Panther Express195.12.231.220unknownPWS/1.1.2916-Dec-2007
Panther Express195.12.231.210LinuxPWS/1.1.2924-Nov-2007
Panther Express195.12.231.220unknownPWS/1.1.2922-Nov-2007
Panther Express195.12.231.209LinuxPWS/1.1.2922-Nov-2007
Panther Express195.12.231.205LinuxPWS/1.1.25 2-Nov-2007
Panther Express195.12.231.217unknownPWS/1.1.2231-Oct-2007
Panther Express195.12.231.199LinuxPWS/1.1.2229-Oct-2007
Panther Express195.12.231.205unknownPWS/1.1.2019-Oct-2007

 Apparently, webkinz team has been working very hard to accommodate the potential load, upgrading web server a couple of  times within the last 2 months.  Their hosts are running various version of PWS.

 What kind of web server is PWS?  I've never heard of it.  After some search, I found out this definition on webopedia:

(2) When capitalized as Personal Web Server, the name of Microsoft’s Web server program for individuals hosting Web page files from a personal computer. Personal Web Server is a smaller-scale version of Microsoft’s IIS technology and is therefore limited in its capabilities. It is designed to support Web sites that obtain limited traffic and/or to be used as a staging server for building pages that will be transferred to a server that can handle large amounts of traffic.

 Bold font are by me for emphasis.  What a surprise and what a disappointment!  A crippled version of IIS.  (Note: This is in fact incorrect.  Please see Jason's comments below about webkinz's network infrastructure.)  That's what is powering the site that attracts millions of kids and parents around the globe.  For millions of webkinzs Santa gave out last night, they can't really be played online.  Then they are just a plain plush toy that is not even worth half the price.  Sorry, Santa, I know it's not your fault, but can I exchange it for a walking doodle?

Seriously, the infrastructure of webkinz site is underdeveloped no matter how hard you upgrade or patch it.  Here is a message to webkinz team, on behalf of my daughter, get some real hardware, now.  Sun servers are quite affordable these days.  For less than the price of 80 webkinzs (80*14.99=$1199.2), you can get a Sun Fire X2100 M2 server, two-way x64, high performance, and energy efficient, and free 60-day trial.

In addition, get the real OS, free.  Get the real application/web server, be it Apache, Sun web server, or Glassfish.

Some of these may already on your wish list, and hopefully Santa already delivered some last night.  But if Santa leaves a PWS/IIS under the Christmas tree, keep it for personal use.

http://blogs.sun.com/chengfang/date/20070329 Thursday March 29, 2007

A generic BeanFactory class for custom JNDI resource

In my previous 3 posts(post 1, post 2, and post 3, I wrote about how to create, inject, look up, and configure a custom JNDI resource in glassfish application server. Usually a custom JNDI resource type conform to JavaBeans conventions, with property fields, getters and setters. Therefore, we should be able to write a generic bean factory class that works with any such custom JNDI resource types.

Just to recap, to create a custom JNDI resource, we need at least 2 classes: (1) the resource class to represent your resource, and (2) the factory class that knows how to create instances of your resource. The factory class must implement interface javax.naming.spi.ObjectFactory, which has a single method:


public Object getObjectInstance(Object obj,
                         Name name,
                         Context nameCtx,
                         Hashtable<?,?> environment)
                         throws Exception

Actually, there is already such a bean factory class org/apache/naming/factory/BeanFactory.class in glassfish lib/appserv-rt.jar. Its source code can be viewed here. But I found I have to modify 1 lines to make it work, otherwise the lookup or injection result is always null.


diff -w -u -b -r1.3 BeanFactory.java
--- BeanFactory.java    6 Nov 2006 21:14:08 -0000       1.3
+++ BeanFactory.java    9 Mar 2007 18:09:56 -0000
@@ -121,7 +121,7 @@
                                     Hashtable environment)
         throws NamingException {

-        if (obj instanceof ResourceRef) {
+        if (obj instanceof Reference) {
For your convenience, the modified generic object factory class is copied below:
package customjndi;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import javax.naming.Reference;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.spi.ObjectFactory;

public class GenericObjectFactory implements ObjectFactory {
    private static final Logger logger = Logger.getLogger(GenericObjectFactory.class.getName());

    public Object getObjectInstance(Object obj, Name name, Context nameCtx,
	    Hashtable environment)
	    throws NamingException {
	logger.fine("obj=" + obj);
	logger.fine("name=" + name);
	logger.fine("nameCtx=" + nameCtx);
	if (obj instanceof Reference) {
	    try {
		Reference ref = (Reference) obj;
		String beanClassName = ref.getClassName();
		Class beanClass = null;
		ClassLoader tcl =
			Thread.currentThread().getContextClassLoader();
		if (tcl != null) {
		    try {
			beanClass = tcl.loadClass(beanClassName);
		    } catch (ClassNotFoundException e) {
		    }
		} else {
		    try {
			beanClass = Class.forName(beanClassName);
		    } catch (ClassNotFoundException e) {
			e.printStackTrace();
		    }
		}
		if (beanClass == null) {
		    throw new NamingException("Class not found: " + beanClassName);
		}

		BeanInfo bi = Introspector.getBeanInfo(beanClass);
		PropertyDescriptor[] pda = bi.getPropertyDescriptors();

		Object bean = beanClass.newInstance();

		Enumeration e = ref.getAll();
		while (e.hasMoreElements()) {

		    RefAddr ra = (RefAddr) e.nextElement();
		    String propName = ra.getType();

		    String value = (String) ra.getContent();

		    Object[] valueArray = new Object[1];

		    int i = 0;
		    for (i = 0; i < pda.length; i++) {

			if (pda[i].getName().equals(propName)) {

			    Class propType = pda[i].getPropertyType();

			    if (propType.equals(String.class)) {
				valueArray[0] = value;
			    } else if (propType.equals(Character.class) || propType.equals(char.class)) {
				valueArray[0] = Character.valueOf(value.charAt(0));
			    } else if (propType.equals(Byte.class) || propType.equals(byte.class)) {
				valueArray[0] = Byte.valueOf(value);
			    } else if (propType.equals(Short.class) || propType.equals(short.class)) {
				valueArray[0] = Short.valueOf(value);
			    } else if (propType.equals(Integer.class) || propType.equals(int.class)) {
				valueArray[0] = Integer.valueOf(value);
			    } else if (propType.equals(Long.class) || propType.equals(long.class)) {
				valueArray[0] = Long.valueOf(value);
			    } else if (propType.equals(Float.class) || propType.equals(float.class)) {
				valueArray[0] = Float.valueOf(value);
			    } else if (propType.equals(Double.class) || propType.equals(double.class)) {
				valueArray[0] = Double.valueOf(value);
			    } else {
				throw new NamingException("String conversion for property type '" + propType.getName() + "' not available");
			    }

			    Method setProp = pda[i].getWriteMethod();
			    if (setProp != null) {
				setProp.invoke(bean, valueArray);
			    } else {
				throw new NamingException("Write not allowed for property: " + propName);
			    }

			    break;

			}

		    }

		    if (i == pda.length) {
			throw new NamingException("No set method found for property: " + propName);
		    }

		}

		return bean;

	    } catch (java.beans.IntrospectionException ie) {
		throw new NamingException(ie.getMessage());
	    } catch (java.lang.IllegalAccessException iae) {
		throw new NamingException(iae.getMessage());
	    } catch (java.lang.InstantiationException ie2) {
		throw new NamingException(ie2.getMessage());
	    } catch (java.lang.reflect.InvocationTargetException ite) {
		throw new NamingException(ite.getMessage());
	    }

	} else {
	    return null;
	}

    }
}

For more details, see glassfish dev email alias discuss on Factory class for custom JNDI resource

Tags: , , , ,