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