Sunday Mar 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

Thursday Mar 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

Friday Mar 09, 2007

How to parameterize and configure custom resources

In my previous two posts (post1 and post2), I demonstrated how to create and inject custom resources in Glassfish application server. However, the custom resource used there has a hard-coded name attribute and thus cannot be parameterized. In this post, I will modify a few steps and files to make it configurable, so that the same resource type and factory can be applied to multiple resources.

1. Specify additional properties when creating custom resource:


asadmin create-custom-resource --restype foo.Widget 
--factoryclass foo.WidgetFactory
--property name=widget-two
--description "this is widget-two"
custom/widget-two

 

It's also possible to specify multiple key-value pairs in the form of key1=val1:key2=val2:key3=val3.

2. Modify foo.WidgetFactory.getObjectInstance method:


    public Object getObjectInstance(Object obj, 
                                    Name name, 
                                    Context nameCtx, 
                                    Hashtable<?, ?> environment) 
        throws Exception {
        Widget widget = new Widget();
        if(obj instanceof Reference) {
            Reference reference = (Reference) obj;
            Enumeration<RefAddr> attributes = reference.getAll();
            widget.init(attributes);
        }
        return widget;
    }

 

I also added a init method to foo.Widget to initialize fields:


    public void init(Enumeration<RefAddr> attributes) {
        while(attributes.hasMoreElements()) {
            RefAddr refAddr = (RefAddr) attributes.nextElement();
            if("name".equals(refAddr.getType())) {
                setName((String) refAddr.getContent());
            }
        }
    }

 

3. Modify the servlet class to inject multiple custom resources with different values but same type and factory class:


public class FooServlet extends HttpServlet {
    @Resource(name="widget-one", mappedName="custom/widget-one")
    private Widget widget1;

    @Resource(name="widget-two", mappedName="custom/widget-two")
    private Widget widget2;

    @Resource(name="widget-three", mappedName="custom/widget-three")
    private Widget widget3;
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet FooServlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Servlet FooServlet at " + request.getContextPath() + "</h1>");
        out.println("<p>Injected custom resource: " + widget1 + "<br>");
        out.println("Custom resource from JNDI lookup: " + lookupWidget("widget-one") + "</p>");
        out.println("<p>Injected custom resource: " + widget2 + "<br>");
        out.println("Custom resource from JNDI lookup: " + lookupWidget("widget-two") + "</p>");
        out.println("<p>Injected custom resource: " + widget3 + "<br>");
        out.println("Custom resource from JNDI lookup: " + lookupWidget("widget-three") + "</p>");
        out.println("</body>");
        out.println("</html>");
    }

 

To look up custom resources without using injection, just configure them in web.xml (or ejb-jar.xml, application-client.xml). Note that the you need to use resource-env-ref, not resource-ref elements:


    <resource-env-ref>
        <resource-env-ref-name>widget-one</resource-env-ref-name>
        <resource-env-ref-type>foo.Widget</resource-env-ref-type>
        <mapped-name>custom/widget-one</mapped-name>
    </resource-env-ref>
    <resource-env-ref>
        <resource-env-ref-name>widget-two</resource-env-ref-name>
        <resource-env-ref-type>foo.Widget</resource-env-ref-type>
        <mapped-name>custom/widget-two</mapped-name>
    </resource-env-ref>
    <resource-env-ref>
        <resource-env-ref-name>widget-three</resource-env-ref-name>
        <resource-env-ref-type>foo.Widget</resource-env-ref-type>
        <mapped-name>custom/widget-three</mapped-name>
    </resource-env-ref>

 

4. Build, deploy the war and view the servlet output at http://localhost:8080/WebApplication1/FooServlet


Thursday Mar 08, 2007

How to inject and look up custom resources in Glassfish

In my previous post, I wrote about how to create a custom resource in Glassfish. In this entry I will talk about how to inject and look up such custom resources after they have been created in the server.

1. Make these custom resource classes and factory classes available to the server. There are various ways to do that, and I suggest copying them to domains\\domain1\\lib\\classes. This is the content of this directory after copying:


/cygdrive/c/ws/sjsas90/publish/glassfish/domains/domain1/lib/classes > /bin/find .
.
./foo
./foo/Widget.class
./foo/WidgetFactory.class

You may have noticed that the server does not have to load these classes when creating custom resources. But when injecting or looking up the resource, these resource classes must be loadable by the server. Restart the server so the server can pick them up.

2. Write your component classes, e.g., servelt, EJB3 bean class, application client main class, etc. For example:


package foo;

import java.io.\*;
import java.net.\*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.\*;
import javax.servlet.http.\*;

public class FooServlet extends HttpServlet {
    //inject resource into a servlet classinstance variable,    
    //assuming this resource is thread-safe.
    @Resource(name="widget", mappedName="custom/widget")
    private Widget widget;
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet FooServlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Servlet FooServlet at " + request.getContextPath() + "</h1>");
        out.println("<p>Injected custom resource: " + widget + "</p>");
        out.println("<p>Custom resource from JNDI lookup: " + lookupWidget() + "</p>");
        out.println("</body>");
        out.println("</html>");
    }
    
    private Widget lookupWidget() throws ServletException {
        Widget widget = null;
        try {
            javax.naming.InitialContext ic = new javax.naming.InitialContext();
            widget = (Widget) ic.lookup("java:comp/env/widget");
        } catch (NamingException ex) {
            throw new ServletException(ex);
        }
        return widget;
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}


web.xml simply declares and maps this servlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>FooServlet</servlet-name>
        <servlet-class>foo.FooServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FooServlet</servlet-name>
        <url-pattern>/FooServlet</url-pattern>
    </servlet-mapping>
</web-app>

Note that for this simple webapp, we don't need sun-web.xml, or any appserver-specific deployment plans. The injected custom resource is resolved by its mappedBy attribute. Portable application should not rely on mappedBy attribute or mapped-by xml element in deployment descriptors.

Another point worth mentioning is, we can look up an injected resource with JNDI. It is particularly useful when we need to access the injected resource outside the injection target class but within the same environment context.

3. Build and deploy the war:


C:\\ws\\sjsas90\\publish\\glassfish\\bin> asadmin deploy \\ws\\nb\\WebApplication1\\dist\\WebApplication1.war
Command deploy executed successfully.

4. View the servlet output http://localhost:8080/WebApplication1/FooServlet



Wednesday Mar 07, 2007

How to create custom resources in Glassfish

This post shows how to create a custom resource in Glassfish application server. These steps should also work in JavaEE SDK 5, Sun Java System Application Server 9.x. This use case should be supported by all compliant JavaEE application servers, though configurations may vary.

0. Download and install Glassfish. Or You can download and the install official releases of JavaEE SDK 5 and Sun Java System Application Server 9.0 here

1. Create your custom resource class. The following is a simple example:


package foo;

/\*\*
 \* A simple custom resource class.
 \*/
public class Widget implements java.io.Serializable {
    private String name;
    
    public Widget() {
    }
    
    public Widget(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Widget " + name;
    }

    /\* (non-Javadoc)
     \* @see java.lang.Object#hashCode()
     \*/
    @Override
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = PRIME \* result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    /\* (non-Javadoc)
     \* @see java.lang.Object#equals(java.lang.Object)
     \*/
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final Widget other = (Widget) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

2. Create your custom resource factory class. The following is one such factory for the above resource class (NOTE: this is a simplistic impl of object factory and only works for hello-world-type of applications.  See here for a generic and real object factory class.)


package foo;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;

/\*\*
 \* A simple factory class for creating custom JNDI resource.  In
 \* real applications, it should be able to configure and parameterize the resource.
 \*/
public class WidgetFactory implements javax.naming.spi.ObjectFactory {
    public WidgetFactory() {
    }

    public Object getObjectInstance(Object obj, 
                                    Name name, 
                                    Context nameCtx, 
                                    Hashtable<?, ?> environment) 
        throws Exception {
        Widget widget = new Widget("Rag");
        System.out.println("Creating " + widget);
        return widget;
    }
}

3. Start the application server and create the custom resource in the server.


C:\\ws\\sjsas90\\publish\\glassfish\\bin> asadmin start-domain
C:\\ws\\sjsas90\\publish\\glassfish\\bin> asadmin create-custom-resource --restype foo.Widget --factoryclass foo.WidgetFactory custom/widget
Command create-custom-resource executed successfully.
The above command creates a custom resource with JNDI name custom/widget. To list all custom resources:

C:\\ws\\sjsas90\\publish\\glassfish\\bin> asadmin list-custom-resources
custom/widget
Command list-custom-resources executed successfully.

To delete a custom resource:

C:\\ws\\sjsas90\\publish\\glassfish\\bin> asadmin delete-custom-resource custom/widget
Command delete-custom-resource executed successfully.

For a full explanation of these asadmin commands and parameters, please run help commands:

asadmin help create-custom-resource
asadmin help list-custom-resources
asadmin help delete-custom-resource

or, 
asadmin create-custom-resource --help
asadmin list-custom-resources --help
asadmin delete-custom-resource --help


About

Cheng Fang

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today