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



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