Tags that Define EL Variables

An EL variable is an attribute of the JSP page context. A variable can be added using the JSTL <c:set> action, or the setAttribute() method of the instance variable called pageContext that points to the javax.servlet.jsp.PageContext object of the Web page. The setAttribute() method takes the following parameters:

  • The name of the scripting variable. This name is used to refer to the variable on the Web page.

  • The object reference to the variable to be added to the page.

  • The scope of the variable can be one of the following constants defined in PageContext:

    • PAGE_SCOPE Available until the current page processing completes (this is the default)

    • REQUEST_SCOPE Available until the current request completes allowing the variable to be used by other pages should this page forward the HTTP request

    • SESSION_SCOPE Available to all pages in the current session

    • APPLICATION_SCOPE Available until the context is reclaimed

The following example adds a String variable to the context under the name "title" and available to this page and all forwarded pages in this request:

String s = "Example Title";
pageContext.setAttribute("title", s, PageContext.REQUEST_SCOPE);

The same thing can be achieved using JSTL:

<c:set var="title" value="Example Title" scope="request" />

To use EL variables in custom tags, you will need to define each variable in the TLD file with a <variable> element defining the sub-components shown in Table 14.7.

Table 14.7. TLD Tags for Defining Variables
TagDescription
name-givenDefines the name for the scripting variable as a fixed value (cannot be specified if name-from-attribute is defined)
name-from-attributeSpecifies the attribute that is used to define the scripting variable name (cannot be specified if name-given is defined)
variable-classSpecifies the class of the scripting variable
declareSpecifies if the variable is a new object (defaults to true)
scopeDefines the scope of the variable--must be one of NESTED, AT_BEGIN, or AT_END and refers to where in the Web page the variable can be accessed

Using the example title variable would require the following entry in the <tag> section of the TLD:

<variable>
  <name-given>title</name-given>
  <variable-class>java.lang.String</variable-class>
  <declare>true</declare>
  <scope>AT_BEGIN</scope>
</variable>

Variable components must be defined before any attribute components for the tag.

You can use scripting variables in the Job Agency case study you developed yesterday to remove one of the perceived weaknesses of defining beans that require initialization parameters.

As a first step, consider the following code fragment from the advertise.jsp:

<jsp:useBean id="cust" class="web.CustomerBean" scope="request" >
  <jsp:setProperty name="cust" property="login" param="customer"/>
</jsp:useBean>

This fragment creates a JavaBean for the customer information. This code looks clumsy. Ideally, you should be able to create the bean and pass in the initialization properties in a single tag. The JSP idiom of setting the bean properties inside the useBean start and end tags is a contrived solution forced on you by the way beans are used in the JSP. With custom tags, you can provide a much cleaner solution. The following useCustomer tag creates the required bean and adds it to the page context:

<agency:useCustomer login="${param.customer}"/>

Looking back at the bean (CustomerBean.java) used to access the customer details, you will see it is a simple adapter for the Advertise Session bean. The CustomerBean's only purpose is to adapt the Session bean interface to the JavaBean semantics required on the Web page. The following code fragment shows part of this Bean class:

public CustomerBean () throws NamingException {
    InitialContext ic = new InitialContext();
    advertiseHome = (AdvertiseHome)ic.lookup("java:comp/env/ejb/Advertise");
}
public void setLogin (String login) throws Exception {
    this.login = login;
    advertise = advertiseHome.create(login);
}
public String getName() throws RemoteException    {
    return advertise.getName();
}

The key points of the Bean class are

  • The bean constructor obtains the home object for the Session bean.

  • The setLogin() method creates the bean as a side effect of setting the login attribute.

  • All the other methods (such as getName()) simply delegate to the appropriate method in the Session bean.

The Advertise Session EJB was developed to conform to the JavaBean semantics for accessing and setting attributes. Using a custom tag, you can use the Session EJB directly without the need for a bean wrapper class. Listing 14.10 shows the UseCustomerTag.java class that creates the Advertise Session bean for theadvertise.jsp page.

Listing 14.10. Full Text of UseCustomerTag.java
package webagency;

import javax.naming.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import agency.*;

public class UseCustomerTag extends TagSupport {
    private String login;

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }
    public int doStartTag() throws JspException {
        try {
           InitialContext ic = new InitialContext();
           AdvertiseHome advertiseHome = (AdvertiseHome)ic.lookup("java:comp/env/ejb
/Advertise");
           Advertise advertise = advertiseHome.create(login);
           pageContext.setAttribute("cust", advertise, PageContext.REQUEST_SCOPE);
        }
        catch (Exception ex) {
            throw new JspTagException("UseCustomerTag: "+ex);
        }
        return SKIP_BODY;
     }

    public int doEndTag() {
        return EVAL_PAGE;
    }
}

The doStartTag() method finds and creates the Advertise Session EJB using the login name passed as an attribute to the tag. The created bean is added to the page context using the name cust, and its scope is set to the current request. Because the session bean uses the same properties as the CustomerBean wrapper class, there are no additional changes required to the JSP code.

Listing 14.11 shows the useCustomer TLD entry with the variable and attribute tags. Note that the login attribute must have an rtexprvalue of true to allow the Web page to pass in the value from the HTTP request parameter.

Listing 14.11. getCust Tag Entry in agency.tld
<tag>
    <name>useCustomer</name>
    <tag-class>webagency.UseCustomerTag</tag-class>
    <body-content>empty</body-content>
    <variable>
      <name-given>cust</name-given>
      <variable-class>agency.Advertise</variable-class>
      <declare>true</declare>
      <scope>AT_BEGIN</scope>
    </variable>
    <attribute>
      <name>login</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>

To keep the example code simple, it always stores the bean against the name cust. To be more flexible, you could add an additional parameter (such as beanName) to be used to allow the customer bean variable name to be specified by the JSP developer. In this case, you would set the TLD <variable> information to use this parameter using the <name-from-attribute>beanName<name-from-attribute/> tag.

You can write custom tags for the other Session EJBs (Agency, AdvertiseJob and Register) along the same lines. Doing this will result in the new customer.jsp page shown in Listing 14.12.

Listing 14.12. Full Text of advertise.jsp
<HTML>
  <%@include file="header.jsf" %>
  <agency:useCustomer login="${param.customer}"/>
  <BODY>
    <H1>${agency.agencyName}</H1>

    <H2>Customer details for: ${cust.login}</H2>
    <FORM action='<c:url value="/customer/updateCustomer"/>'>
      <INPUT type="hidden" name="login" value="${cust.login}">
      <TABLE>
        <TR>
          <TD>Login:</TD>
          <TD>${cust.login}</TD>
        </TR>
        <TR>
          <TD>Name:</TD>
          <TD><input type="text" name="name" value="${cust.name}"></TD>
        </TR>
        <TR>
          <TD>Email:</TD>
          <TD><input type="text" name="email" value="${cust.email}"></TD>
        </TR>
        <TR>
          <TD>Address:</TD>
          <TD><input type="text" name="address" value="${cust.address[0]}"></TD>
        </TR>
        <TR>
          <TD>Address:</TD>
          <TD><input type="text" name="address" value="${cust.address[1]}"></TD>
        </TR>
      </TABLE>
      <INPUT type="submit" value="Update Details">
      <INPUT type="reset">
    </FORM>
    <FORM action='<c:url value="/customer/deleteCustomer"/>'>
      <INPUT type="hidden" name="customer" value="${cust.login}">
      <INPUT type="submit" value="Delete Customer ${cust.login}">
    </FORM>

    <H2>Jobs</H2>
    <c:forEach var="jobRef" items="${cust.jobs}" >
      <agency:useJob customer="${cust.login}" ref="${jobRef}"/>
      <H3>${job.ref}</H3>
      <FORM action='<c:url value="/customer/updateJob"/>'>
        <TABLE>
          <TR>
            <TD>Description:</TD>
            <TD><input type="text" name="description" value="${job.description}"></TD>
          </TR>
          <TR>
            <TD>Location:</TD>
            <TD>
              <SELECT name="location">
                <c:forEach var="location" items="${agency.locations}" >
                  <agency:option option="${location}" selected="${job.location}"/>
                </c:forEach>
              </SELECT>
            </TD>
          </TR>
          <TR>
            <TD>Skills:</TD>
            <TD>
              <SELECT name="skills" multiple size="6">
                <c:forEach var="agencySkill" items="${agency.skills}" >
                  <agency:option option="${agencySkill}" selected="${job.skills}"/>
                </c:forEach>
              </SELECT>
            </TD>
          </TR>
        </TABLE>
        <INPUT type="hidden" name="customer" value="${job.customer}">
        <INPUT type="hidden" name="ref" value="${job.ref}">
        <INPUT type="submit" value="Update Job">
      </FORM>
      <FORM action='<c:url value="/customer/deleteJob"/>'>
        <INPUT type="hidden" name="customer" value="${job.customer}">
        <INPUT type="hidden" name="ref" value="${job.ref}">
        <INPUT type="submit" value="Delete Job ${job.ref}">
      </FORM>
    </c:forEach>

    <H2>Create New Job</H2>
    <FORM action='<c:url value="/customer/createJob"/>'>
      <TABLE>
        <TR>
          <TD>Ref:</TD>
          <TD><INPUT type="text" name="ref"></TD>
        </TR>
        <TR>
          <INPUT type="hidden" name="customer" value="${cust.login}">
          <TD colspan="2"><INPUT type="submit" value="Create Job"></TD>
        </TR>
      </TABLE>
    </FORM>
    <%@include file="footer.jsf" %>
  </BODY>
</HTML>

You can build and deploy the updated Agency case study from the Day14/examples directory using

asant build deploy

Browse to the URL http://localhost:8000/webagency to view the resulting pages. The Agency Web pages won't look any different from yesterday's pages, but you know the underlying implementation is much better.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.19.185