2/18/2012

How to Create POJO JavaBean Custom Resource in GlassFish

In addition to simple value custom resources, GlassFish also provides decent support for POJO JavaBean custom resources. The steps are very similar to String and primitive custom resources, except that you will need to provide your resource impl class and use a different GlassFish factory class. For example, suppose we need to implement a Person class:


public class Person implements java.io.Serializable {
private String firstName;
private String lastName;
private int age;

public String getFirstName() {
return firstName;
}

public void setFirstName(String s) {
firstName = s;
}

public String getLastName() {
return lastName;
}

public void setLastName(String s) {
lastName = s;
}

public int getAge() {
return age;
}

public void setAge(int i) {
age = i;
}

@Override
public String toString() {
return String.format("Person firstName:%s, lastName:%s, age:%s",
firstName, lastName, age);
}
//TODO override equals and hashCode
}
Compile it and copy Person.class to GlassFish domain lib directory, restart the domain, and create a custom resource of type Person:

$ javac Person.java
$ cp Person.class $GLASSFISH_HOME/domains/domain1/lib/classes/
$ asadmin restart-domain
$ asadmin create-custom-resource --restype=Person --factoryclass=org.glassfish.resources.custom.factory.JavaBeanFactory --property firstName\="Jon":lastName\="Smith":age\=20 resource/person
To list the attributes and properties of the newly-created resource with GlassFish asadmin get command:

$ asadmin get 'resources.custom-resource.resource/person.*'

resources.custom-resource.resource/person.property.age=15
resources.custom-resource.resource/person.property.lastName=Smith
resources.custom-resource.resource/person.property.firstName=Jon
resources.custom-resource.resource/person.enabled=true
resources.custom-resource.resource/person.factory-class=org.glassfish.resources.custom.factory.JavaBeanFactory
resources.custom-resource.resource/person.jndi-name=resource/person
resources.custom-resource.resource/person.object-type=user
resources.custom-resource.resource/person.res-type=Person
Command get executed successfully.
To update the age property of the resource with asadmin set command:

$ asadmin set 'resources.custom-resource.resource/person.property.age'=15

resources.custom-resource.resource/person.property.age=15
Command set executed successfully.
To look up the custom resource, resource/person, from a webapp, or Java EE application:

try {
InitialContext ic = new InitialContext();
Person person = (Person) ic.lookup("resource/person");
} catch (NamingException e) {
throw new RuntimeException(e);
}
You can inject it into Java EE web component or EJB component class such as servlet, filter, web listener, interceptor, or EJB bean class:

@Resource(lookup="resource/person")
private Person person;
A Java SE remote client can also look up the resource:

import javax.naming.*;
/**
* A generic remote client for testing JNDI lookup.
*/
public class TestLookup {
public static void main(String args[]) throws Exception {
InitialContext ic = new InitialContext();
for(String name : args) {
System.out.printf("Looked up jndi name %s, got %s%n",
name, ic.lookup(name));
}
}
}
The following shows how to build and run the remote JNDI client, and the output:

$ javac TestLookup.java
$ java -cp "$GLASSFISH_HOME/modules/*:." TestLookup resource/person

Feb 18, 2012 11:42:12 AM com.sun.enterprise.v3.server.CommonClassLoaderServiceImpl findDerbyClient
INFO: Cannot find javadb client jar file, derby jdbc driver will not be available by default.
Looked up jndi name resource/person, got Person firstName:Jon, lastName:Smith, age:15
Note that both TestLookup.class and Person.class are in current directory and therefore are in the client classpath. Person class also implements java.io.Serializable to make remote access possible.

For more advanced example of GlassFish custom resources, see How to create and look up thread pool resource in GlassFish

2/04/2012

How to Create Simple String and Primitive Resources in GlassFish

Sometimes you need to create simple resources in application server so that all deployed applications can look them up. Their types can be string, boolean, number, or any custom java bean types. In GlassFish CLI, they are created and managed with a set of generic commands,


asadmin create-custom-resource ...
asadmin list-custom-resources ...
asadmin delete-custom-resource ...
asadmin get 'resources.custom-resource.*'
asadmin set ...
GlassFish admin console provides GUI way of doing things but I found using CLI is a lot faster.

For example:
$ asadmin create-custom-resource --restype=java.lang.String --factoryclass=org.glassfish.resources.custom.factory.PrimitivesAndStringFactory --property value="http\://javahowto.blogspot.com" resource/javahowto

$ asadmin create-custom-resource --restype=java.lang.Double --factoryclass=org.glassfish.resources.custom.factory.PrimitivesAndStringFactory --property value=0.5 resource/rate

$ asadmin create-custom-resource --restype=java.lang.Boolean --factoryclass=org.glassfish.resources.custom.factory.PrimitivesAndStringFactory --property value=true resource/flag
To look up the custom resource created above, just perform the following in any web or EJB component classes, e.g., servlet, filter, interceptor, web listener, EJB bean class:
try {
InitialContext ic = new InitialContext();
String javahowto = (String) ic.lookup("resource/javahowto");
double rate = (Double) ic.lookup("resource/rate");
boolean flag = (Boolean) ic.lookup("resource/flag");
System.out.printf(
"custom resources from lookup: javahowto=%s, rate=%s, flag=%s%n",
javahowto, rate, flag);
} catch (NamingException e) {
throw new RuntimeException(e);
}
An easier way to obtain these resources is through @Resource injection in any web or EJB component class:
  @Resource(lookup="resource/javahowto")
private String withLookup;

@Resource(lookup="resource/rate")
private double rate;

@Resource(lookup="resource/flag")
private boolean flag;
These custom resources can also be accessed from a remote Java SE client:

import javax.naming.*;

/**
* A generic remote client for testing JNDI lookup.
*/
public class TestLookup {
public static void main(String args[]) throws Exception {
InitialContext ic = new InitialContext();
for(String name : args) {
System.out.printf("Looked up jndi name %s, got %s%n",
name, ic.lookup(name));
}
}
}
To compile and run the remote client:

javac TestLookup.java
java -cp "$GLASSFISH_HOME/modules/*:." TestLookup resource/javahowto resource/rate resource/flag

Feb 16, 2012 8:21:21 PM com.sun.enterprise.v3.server.CommonClassLoaderServiceImpl findDerbyClient
INFO: Cannot find javadb client jar file, derby jdbc driver will not be available by default.
Looked up jndi name resource/javahowto, got http://javahowto.blogspot.com
Looked up jndi name resource/rate, got 0.5
Looked up jndi name resource/flag, got true
The warning message "Cannot find javadb client jar file" can be safely ignored. To avoid this annoying message, just add command line system property AS_DERBY_INSTALL, pointing to a valid derby installation:

java -cp "$GLASSFISH_HOME/modules/*:." -DAS_DERBY_INSTALL=$GLASSFISH_HOME/../javadb TestLookup resource/javahowto resource/rate resource/flag
You can view all attributes and properties of a custom resource with asadmin get command:

asadmin get 'resources.custom-resource.resource/rate.*'

resources.custom-resource.resource/rate.property.value=0.6
resources.custom-resource.resource/rate.enabled=true
resources.custom-resource.resource/rate.factory-class=org.glassfish.resources.custom.factory.PrimitivesAndStringFactory
resources.custom-resource.resource/rate.jndi-name=resource/rate
resources.custom-resource.resource/rate.object-type=user
resources.custom-resource.resource/rate.res-type=java.lang.Double
Command get executed successfully.
To update the value of a custom resource with asadmin set command:

asadmin set 'resources.custom-resource.resource/rate.property.value'=0.6
resources.custom-resource.resource/rate.property.value=0.6
Command set executed successfully.
The updated value is visible to the client application immediately without server restart.