[go: up one dir, main page]

0% found this document useful (0 votes)
20 views59 pages

Enterprise Java and UML - 668632

The document outlines the structure and interfaces of various entity beans in an Enterprise Java application, specifically focusing on TimeEntry, ChargeCode, and Client entities. It details their local and home interfaces, methods for creating and finding beans, and the implementation of primary key classes. The document serves as a technical reference for developers working with these entity beans in the context of Java EE applications.

Uploaded by

Phan Duc Tri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views59 pages

Enterprise Java and UML - 668632

The document outlines the structure and interfaces of various entity beans in an Enterprise Java application, specifically focusing on TimeEntry, ChargeCode, and Client entities. It details their local and home interfaces, methods for creating and finding beans, and the implementation of primary key classes. The document serves as a technical reference for developers working with these entity beans in the context of Java EE applications.

Uploaded by

Phan Duc Tri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 59

OMG PRESS

Enterprise Java ™

UML

and
2nd Edition

CT Arrington, Syed Rayhan


267783 WS01.qxd 5/5/03 9:17 AM Page 1

TimeEntryEntityBean

TimeEntryInt.java
TimeEntryLocal.java is the local interface for the TimeEntry entity bean. It defines the
locally accessible methods for the TimeEntry entity bean. This is shown in Figure 01.

<<EntityLocal>>
TimeEntryLocal

+ getHours() : int
+ getDate() : Date
+ getChargeCode() : ChargeCodeLocal
+ getTimecard() : TimecardLocal
+ setHours(hours : int)
+ setDate(day : Date)
+ setChargeCode(code : ChargeCodeLocal)

Figure 01 Local interface of the TimeEntry entity bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;
import java.util.*;
import javax.ejb.*;
/**
* The TimeEntryInt is the interface that ties the Bean with the Remote
1
267783 WS01.qxd 5/5/03 9:17 AM Page 2

2 TimeEntryEntityBean

* interface to provide compile time type checking.


*/
public interface TimeEntryInt
{
/** Answers a ChargeCode for this TimeEntry. */
public ChargeCodeLocal getChargeCode();

/** Answers the hour charged in this TimeEntry. */


public int getHours();

/** Answers the day the time is entered for. */


public Date getDate();

/** Answers the timecard it belongs to. */


public TimecardLocal getTimecard();

/** sets a ChargeCode for this TimeEntry. */


public void setChargeCode(ChargeCodeLocal ccode);

/** sets the hour charged in this TimeEntry. */


public void setHours(int hours);

/** sets the day the time is entered for. */


public void setDate(Date date);
}

TimeEntryLocal.java
TimeEntryLocal.java is the local EJB interface that inherits from TimeEntryInt and
hence the body is empty. This is in line with what we have set as our implementation
strategy for all of our EJBs.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The TimeEntry bean holds a single time entry.
* TimeEntryLocal is the local interface through which local clients
* access the underlying entity bean.
*/
public interface TimeEntryLocal extends EJBLocalObject, TimeEntryInt
{
}
267783 WS01.qxd 5/5/03 9:17 AM Page 3

TimeEntryEntityBean 3

TimeEntrytLocalHome.java
TimeEntryLocalHome.java is the Home interface for the TimeEntry entity bean. It
defines the methods for finding and creating TimeEntry entity beans. This is shown in
Figure 02.

<<EntityLocalHome>>
TimeEntryLocalHome

+ create(id : String, hour : int, day : Date, code : ChargeCodeLocal, tcard : TimecardLocal) : TimeEntryLocal
+ findByPrimaryKey(key : TimeEntryPK) : TimeEntryLocal
+ findByTimecard(tcardId : String) : Collection

Figure 02 Local Home interface of the TimeEntry entity bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The TimeEntry bean holds a single time entry.
*
* TimeEntryLocalHome is the local interface through which local clients
* find and create the underlying entity beans.
*
*/
public interface TimeEntryLocalHome extends EJBLocalHome
{
/** Answers a local reference to the newly created Timecard bean. */
public TimeEntryLocal create(String timeEntryId, Date day, int Æ
hours, ChargeCodeLocal code,
TimecardLocal tcard) Æ
throws CreateException;

/** Answers a Collection of references to TimeEntries for a Æ


specific Timecard. */
public Collection findByTimecard(String timecardId) throws Æ
FinderException;

/** Answers a local reference to the specified TimeEntry, if it Æ


exists. */
public TimeEntryLocal findByPrimaryKey(TimeEntryPK key) throws Æ
FinderException;

}
267783 WS01.qxd 5/5/03 9:17 AM Page 4

4 TimeEntryEntityBean

TimeEntryPK.java
TimeEntryPK.java represents the primary key class of the TimeEntry entity bean. It is
important to note here that it implements hashCode() and equals() methods and imple-
ments the Serializable interface.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.io.Serializable;

/**
* The TimeEntry bean holds a single time entry.
*
* TimeEntryPK is the primary key class for the underlying entity Æ
bean. It is,
* id = timecard-id + entry-count-for-timecard
*/
public class TimeEntryPK implements Serializable
{
public String id;

public TimeEntryPK()
{

public TimeEntryPK(String id)


{
this.id = id;
}

public String toString()


{
return id;
}

public int hashCode()


{
return id.hashCode();
}

public boolean equals(Object key)


{
if (key == null)
{
return false;
}
else
{
267783 WS01.qxd 5/5/03 9:17 AM Page 5

TimeEntryEntityBean 5

if (!key.getClass().equals(this.getClass()))
{
return false;
}
else
{
return ((TimeEntryPK)key).id.equals(this.id);
}
}
}
}

TimeEntryBean.java
TimeEntryBean.java is the implementation class for the TimeEntry entity bean. It pro-
vides the data and logic for the bean. Again, there is not much to it. Each TimeEntry
entity bean holds an ID, total hours worked, the day of the work, a reference to the
charge code entity bean, and a reference to the timecard entity bean to which it
belongs.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;

/**
* The TimeEntry bean holds time entries for a date range.
* TimeEntryBean is the actual entity bean implementation.
*/

public abstract class TimeEntryBean extends BasicEntityBean Æ


implements TimeEntryInt
{

/** CMP fields */


public abstract String getId();
public abstract void setId(String id);
public abstract long getDay();
public abstract void setDay(long day);
public abstract int getHours();
public abstract void setHours(int hours);

/** CMR fields */


public abstract TimecardLocal getTimecard();
public abstract void setTimecard(TimecardLocal card);
public abstract ChargeCodeLocal getChargeCode();
267783 WS01.qxd 5/5/03 9:17 AM Page 6

6 TimeEntryEntityBean

public abstract void setChargeCode(ChargeCodeLocal code);

/**
* Create an TimeEntryBean with the specified parameters. This is
* never called directly.
*/
public TimeEntryPK ejbCreate(String timeEntryId, Date day, int hours,
ChargeCodeLocal code, TimecardLocal tcard) throws Æ
CreateException
{
System.out.println(“in ejbCreate() of TimeEntryBean!”);
// sets the CMP fields
setId(timeEntryId);
setDay(day.getTime());
setHours(hours);
return null;
}

/** Actions performed after creation. This is never called directly. */


public void ejbPostCreate(String timeEntryId, Date day, int hours,
ChargeCodeLocal code, TimecardLocal tcard)
{
System.out.println(“in ejbPostCreate() of TimeEntryBean!”);
//sets CMR fields
setChargeCode(code);
setTimecard(tcard);
}

/** Answers the day the time is entered for. */


public Date getDate()
{
return new Date(getDay());
}

/** sets the day the time is entered for. */


public void setDate(Date date)
{
setDay(date.getTime());
}
}
267783 WS02.qxd 5/5/03 9:17 AM Page 7

ChargeCodeEntityBean

ChargeCodeInt.java
ChargeCodeInt.java is the local Business interface for the ChargeCode entity bean. It
defines all of the locally accessible methods for the ChargeCode entity bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import javax.ejb.*;

/**
* The ChargeCodeInt is the interface that ties the Bean with the Remote
* interface to provide compile time type checking.
*/
public interface ChargeCodeInt
{
/** Answers the name of this ChargeCode. */
public String getName();

/** Answers the description of this ChargeCode. */


public String getDescription();

/** Answers the parent Project of this ChargeCode. */


public ProjectLocal getProject();
}

7
267783 WS02.qxd 5/5/03 9:17 AM Page 8

8 ChargeCodeEntityBean

ChargeCodeLocal.java
ChargeCodeLocal.java is the local EJB interface for the ChargeCode entity bean that
inherits from ChargeCodeInt.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import javax.ejb.*;

/**
* The ChargeCode bean holds descriptive information about a billable
* charge code. Since each ChargeCode is part of a larger project, the
* parent project can be accessed from the charge code.
* ChargeCodeLocal is the local interface through which local clients
* access the underlying entity bean.
*/
public interface ChargeCodeLocal extends EJBLocalObject, ChargeCodeInt
{
}

ChargeCodeLocalHome
ChargeCodeLocalHome.java is the Home interface for the ChargeCode entity bean. It
defines the methods for finding and creating ChargeCode entity beans.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The ChargeCode bean holds simple descriptive information on a common
* activity that is performed by development teams. This activity may be
* used to create a ChargeCode.
*
* ChargeCodeLocalHome is the local interface through which local
* clients find and create the underlying entity beans.
*
*/
public interface ChargeCodeLocalHome extends EJBLocalHome
{

/** Answers a Collection containing references to each ChargeCode bean


that has the specified project as its parent.*/
public Collection findByProject(long projectId) throws FinderException;

/** Answers a local reference to the ChargeCode bean. */


public ChargeCodeLocal findByName(String projectName, String Æ
chargeCodeName) throws FinderException;

/** Answers a local reference to the ChargeCode bean, if it exists. */


267783 WS02.qxd 5/5/03 9:17 AM Page 9

ChargeCodeEntityBean 9

public ChargeCodeLocal findByPrimaryKey(ChargeCodePK key) throws Æ


FinderException;

/** Answers a local reference to the newly created ChargeCode bean. */


public ChargeCodeLocal create(long id, String name, String Æ
description,
ProjectLocal project) throws Æ
CreateException;
}

ChargeCodeBean.java
ChargeCodeBean.java is the implementation class for the ChargeCode entity bean. It
provides the data and logic for the bean. Again, there is not much to it. Each Charge-
Code entity bean holds an ID, a name, a description, and a reference to the project
entity bean to which it belongs.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import java.util.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;

/**
* The ChargeCode bean holds descriptive information about a billable
* charge code. Since each ChargeCode is part of a larger project, the
* parent project can be accessed from the charge code.
* ChargeCodeBean is the actual entity bean implementation.
*/
public abstract class ChargeCodeBean extends BasicEntityBean Æ
implements ChargeCodeInt
{
/** CMP fields */
public abstract long getId();
public abstract void setId(long id);
public abstract String getName();
public abstract void setName(String name);
public abstract String getDescription();
public abstract void setDescription(String desc);

/** CMR fields*/


public abstract ProjectLocal getProject();
public abstract void setProject(ProjectLocal project);

public ChargeCodeBean()
{
}
267783 WS02.qxd 5/5/03 9:17 AM Page 10

10 ChargeCodeEntityBean

/** Create a ChargeCodeBean with the specified parameters. This Æ


is never called directly. */
public ChargeCodePK ejbCreate(long id, String name, String description,
ProjectLocal project) throws CreateException
{
setId(id);
setName(name);
setDescription(description);
return null;
}

/** Actions performed after creation. This is never called directly. */


public void ejbPostCreate(long id, String name, String description,
ProjectLocal project)
{
setProject(project);
}
}
267783 WS03.qxd 5/5/03 9:17 AM Page 11

ClientEntityBean

ClientInt.java
ClientInt.java is the local Business interface for the Client entity bean. It defines all of
the locally accessible methods for the Client entity bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The ClientInt is the interface that ties the Bean with the Remote
* interface to provide compile time type checking.
*/
public interface ClientInt
{
/** Answers the name of this Client. */
public String getName();

/** Answers the description of this Client. */


public String getDescription();

/** Answers all the projects of this Client. */

11
267783 WS03.qxd 5/5/03 9:17 AM Page 12

12 ClientEntityBean

public Collection getProjects();

ClientLocal.java
ClientLocal.java is the local EJB interface for the Client entity bean that inherits from
ClientInt.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The Client bean holds descriptive information about a client.
* ClientLocal is the local interface through which local clients access
* the underlying entity bean.
*/
public interface ClientLocal extends EJBLocalObject, ClientInt
{
}

ClientLocalHome.java
ClientLocalHome.java is the Home interface for the Client entity bean. It defines the
methods for finding and creating Client entity beans.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The Client bean holds descriptive information about a client.
* ClientLocalHome is the local interface through which local clients
* find and create the underlying entity beans.
*/
public interface ClientLocalHome extends EJBLocalHome
{
/** Answers a Collection that holds references to all of the Client Æ
beans. */
public Collection findAll() throws FinderException;

/**
* Answers a Collection that holds references to all of the Client
* beans that match the name parameter.
*/
public Collection findByName(String name) throws FinderException;

/** Answers a local reference to the Client bean, if it exists. */


267783 WS03.qxd 5/5/03 9:17 AM Page 13

ClientEntityBean 13

public ClientLocal findByPrimaryKey(ClientPK key) throws FinderException;

/** Answers a local reference to the newly created Client bean. */


public ClientLocal create(long id, String name, String description) Æ
throws CreateException;
}

ClientBean.java
ClientBean.java is the implementation class for the Client entity bean. It contains the
data and logic for the bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import java.util.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;

/**
* The Client bean holds descriptive information about a client.
* ClientBean is the actual entity bean implementation.
*/
public abstract class ClientBean extends BasicEntityBean implements Æ
ClientInt
{
/** CMP fields */
public abstract long getId();
public abstract void setId(long id);
public abstract String getName();
public abstract void setName(String name);
public abstract String getDescription();
public abstract void setDescription(String desc);

/** CMR fields */


public abstract Collection getProjects();
public abstract void setProjects(Collection projects);

public ClientBean()
{
}

/** Create a ClientBean with the specified parameters. This is Æ


never called directly. */
public ClientPK ejbCreate(long id, String name, String description) Æ
throws CreateException
{
setId(id);
setName(name);
267783 WS03.qxd 5/5/03 9:17 AM Page 14

14 ClientEntityBean

setDescription(description);
return null;
}

/** Actions performed after creation. This is never called directly. */


public void ejbPostCreate(long id, String name, String description)
{
}
}
267783 WS04.qxd 5/5/03 9:18 AM Page 15

ProjectEntityBean

ProjectInt.java
ProjectInt.java is the local Business interface for the Project entity bean. It defines the
locally accessible methods for the Project entity bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The ProjectInt is the interface that ties the Bean with the Remote
* interface to provide compile time type checking.
*/
public interface ProjectInt
{
/** Answers the name of this Project. */
public String getName();

/** Answers the description of this Project. */


public String getDescription();

/** Answers the parent Client of this Project. */

15
267783 WS04.qxd 5/5/03 9:18 AM Page 16

16 ProjectEntityBean

public ClientLocal getClient();

/** Answers all the charge codes for this Project. */


public Collection getChargeCodes();
}

ProjectLocal.java
ProjectLocal.java is the local EJB interface for the Project entity bean that inherits from
ProjectInt.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The Project bean holds descriptive information about a project.
* ProjectLocal is the local interface through which local clients
* access the underlying entity bean.
*/
public interface ProjectLocal extends EJBLocalObject, ProjectInt
{
}

ProjectLocalHome.java
ProjectLocalHome.java is the Home interface for the Project entity bean. It defines the
methods for finding and creating Project entity beans.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import java.util.*;
import javax.ejb.*;

/**
* The Project bean holds descriptive information about a project.
* ProjectLocalHome is the local interface through which local clients
* find and create the underlying entity beans.
*/

public interface ProjectLocalHome extends EJBLocalHome


{

/** Answers a Collection that contains references to all Projects


associated with the specified client. */
public Collection findByClientId(long clientId) throws FinderException;

/** Answers a Collection that contains references to all Project beans


267783 WS04.qxd 5/5/03 9:18 AM Page 17

ProjectEntityBean 17

that have the specified name. Should be unique. */


public Collection findProject(long clientId, String name) throws Æ
FinderException;

/** Answer a local reference to the Project if it exists. */


public ProjectLocal findByPrimaryKey(ProjectPK key) throws
FinderException;

/** Answer a local reference to the newly created Project. */


public ProjectLocal create(long id, String name, String description,
ClientLocal client) throws CreateException;
}

ProjectBean.java
ProjectBean.java is the implementation class for the Project entity bean. It holds the
data and logic for the bean.

package com.wiley.compBooks.EJwithUML.TimeCardDomain;

import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import java.util.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;

/**
* The Project bean holds descriptive information about a project.
* ProjectBean is the actual entity bean implementation.
*/

public abstract class ProjectBean extends BasicEntityBean implements Æ


ProjectInt
{
/** CMP fields */
public abstract long getId();
public abstract void setId(long id);
public abstract String getName();
public abstract void setName(String name);
public abstract String getDescription();
public abstract void setDescription(String desc);

/** CMR fields*/


public abstract ClientLocal getClient();
public abstract void setClient(ClientLocal client);
public abstract Collection getChargeCodes();
public abstract void setChargeCodes(Collection chargeCodes);

public ProjectBean()
{
267783 WS04.qxd 5/5/03 9:18 AM Page 18

18 ProjectEntityBean

/** Create a ProjectBean with the specified parameters. This is Æ


never called directly. */
public ProjectPK ejbCreate(long id, String name, String description,
ClientLocal client) throws CreateException
{
setId(id);
setName(name);
setDescription(description);
return null;
}

/** Actions performed after creation. This is never called directly. */


public void ejbPostCreate(long id, String name, String description,
ClientLocal client) throws CreateException
{
setClient(client);
}
}
267783 WS05.qxd 5/5/03 9:18 AM Page 19

RecordTimeServletjava

RecordTimeServlet.java
The RecordTimeServlet uses the RecordTimeWorkflow to retrieve and update time-
cards. If no entry or new charge code is specified, the RecordTimeServlet retrieves the
current timecard and builds an entry form. If an entry is submitted, the RecordTime-
Servlet first updates the timecard through the RecordTimeWorkflow and then builds
an entry form. If a new charge code is specified, then the RecordTimeServlet creates
new zero hour entries for the charge code, updates the timecard, and then builds an
entry form.

package com.wiley.compBooks.EJwithUML.TimecardUI;

import javax.servlet.http.*;
import javax.servlet.*;

import javax.naming.*;
import javax.ejb.*;
import java.rmi.*;
import javax.rmi.PortableRemoteObject;
import javax.servlet.http.*;
import javax.servlet.*;

import javax.naming.*;

19
267783 WS05.qxd 5/5/03 9:18 AM Page 20

20 RecordTimeServletjava

import javax.ejb.*;
import java.rmi.*;
import javax.rmi.PortableRemoteObject;

import java.io.*;
import java.util.*;
import java.text.*;

import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.Core.*;
import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.FormPrimitives.*;
import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.Layout.*;
import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.ContentElements.*;
import com.wiley.compBooks.EJwithUML.TimeCardWorkflow.*;
import com.wiley.compBooks.EJwithUML.Dtos.*;
import com.wiley.compBooks.EJwithUML.TimecardProducers.*;
import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import com.wiley.compBooks.EJwithUML.Base.ApplicationExceptions.*;

/**
* The RecordTimeServlet uses the TimecardWorkflow and
* HtmlProduction packages to create the formatted HTML
* for the time entry form and to capture the entered hours.
*/
public class RecordTimeServlet extends BasicTimecardServlet
{
private static final DateFormat longFormat = new SimpleDateFormat Æ
(“MMM dd, yyyy”);
private static final DateFormat shortFormat = new Æ
SimpleDateFormat(“MMM dd”);
private static final DateFormat keyFormat = new Æ
SimpleDateFormat(“MMM.dd.yyyy”);
private static final DateFormat dayOfWeekFormat = new Æ
SimpleDateFormat(“EE”);

public void doGet(HttpServletRequest request, HttpServletResponse Æ


response) throws ServletException, IOException
{
doPost(request, response);
}

/** Overrides method from HttpServlet. doPost is called by the Æ


servlet engine. */
public void doPost(HttpServletRequest request, HttpServletResponse Æ
response) throws ServletException, IOException
{
System.out.println(“RecordTimeServlet: doPost”);
try
{
PagePrimitive page = null;
267783 WS05.qxd 5/5/03 9:18 AM Page 21

RecordTimeServletjava 21

// extract username from session


HttpSession session = request.getSession(false);
String username = (String)
session.getAttribute(TimecardKey.USERNAME.getKeyText());

// extract parameters
String client =
request.getParameter(TimecardKey.CLIENT.getKeyText());
String project =
request.getParameter(TimecardKey.PROJECT.getKeyText());
String code = request.getParameter(TimecardKey.CODE.getKeyText());

// Get workflow and timecard


Context initial = new InitialContext();
Object objref = initial.lookup(EjbReferenceNames.RECORD_TIME_ Æ
WORKFLOW_HOME);
RecordTimeWorkflowHome rtwhome = (RecordTimeWorkflowHome) Æ
PortableRemoteObject.narrow(objref, RecordTimeWorkflowHome.class);
RecordTimeWorkflow rtwf = rtwhome.create(username);
TimecardDTO timecard = rtwf.getCurrentTimecard();

// update and submit timecard


if (request.getParameterMap().containsKey(TimecardKey.SUBMIT_ Æ
TIMECARD.getKeyText()))
{
updateTimecardFromRequest(timecard, request);
rtwf.updateTimecard(timecard);
rtwf.submitTimecard();
}

// save timecard
else if
(request.getParameterMap().containsKey(TimecardKey.SAVE_TIMECARD. Æ
getKeyText()))
{
updateTimecardFromRequest(timecard, request);
rtwf.updateTimecard(timecard);
}

// add charge code


if (client != null && !client.trim().equals(“”))
{
List dates = getDatesInOrder(timecard);
Iterator date_it = dates.iterator();
while (date_it.hasNext())
{
Date current_date = (Date) date_it.next();
TimeEntryDTO te = new TimeEntryDTO(client, code, project, 0, Æ
current_date);
timecard.addEntry(te);
}
267783 WS05.qxd 5/5/03 9:18 AM Page 22

22 RecordTimeServletjava

rtwf.updateTimecard(timecard);
}

// build page from timecard


timecard = rtwf.getCurrentTimecard();
page = buildEntryPage(timecard, username);

// write page to response


StringBuffer buffer = new StringBuffer();
page.buildContent(buffer);
response.getWriter().println(buffer.toString());
response.getWriter().flush();
response.getWriter().close();
}
catch (Exception e)
{
System.out.println(“RecordTimeServlet e:” +e);
throw new ServletException(e);
}
}

private PagePrimitive buildEntryPage(TimecardDTO timecard, String Æ


username)
{
PagePrimitive page = new TimecardPageProducer(“Enter Hours”);

// add welcome message


String start_date = this.longFormat.format(timecard.getStartDate());
String end_date = this.longFormat.format(timecard.getEndDate());
ParagraphPrimitive welcome = new
ParagraphPrimitive(TimecardStyle.IMPORTANT_TEXT, “Welcome “ Æ
+username+ “. Please enter Hours for “ +start_date+ “ to “ +end_date);
page.addToBody(welcome);

// add link to select charge code


LinkPrimitive select_code_link = new
LinkPrimitive(“/Timecard/SelectChargeCodeServlet”);
select_code_link.setStyle(TimecardStyle.IMPORTANT_TEXT);
select_code_link.addText(“Select a Charge Code”);
page.addToBody(select_code_link);

// derive ordered list of dates, ordered list of charge codes and Æ


map of date_code to entries
List dates = getDatesInOrder(timecard);
List codes = getChargeCodesInOrder(timecard);
Map entry_map = getEntriesMap(timecard);

if (!entry_map.isEmpty())
{
267783 WS05.qxd 5/5/03 9:18 AM Page 23

RecordTimeServletjava 23

TablePrimitive table = new TablePrimitive();

// build column headings from dates


Iterator date_it = dates.iterator();
int col_ctr = 1;
while (date_it.hasNext())
{
Date current_date = (Date) date_it.next();
SpanPrimitive date_span = new
SpanPrimitive(TimecardStyle.IMPORTANT_TEXT, “”);
date_span.addText(dayOfWeekFormat.format(current_date));
date_span.addLineBreak();
date_span.addText(shortFormat.format(current_date));

table.setPrimitiveAt(0, col_ctr++, date_span);


}

// build row headings from charge codes


Iterator codes_it = codes.iterator();
int row_ctr = 1;
while (codes_it.hasNext())
{
String code = (String) codes_it.next();
SpanPrimitive code_span = new
SpanPrimitive(TimecardStyle.IMPORTANT_TEXT, code);
table.setPrimitiveAt(row_ctr++, 0, code_span);
}

// build each text entry field


date_it = dates.iterator();
col_ctr = 1;
while (date_it.hasNext())
{
Date date = (Date) date_it.next();
String date_string = keyFormat.format(date);

codes_it = codes.iterator();
row_ctr = 1;
while (codes_it.hasNext())
{
String code = (String) codes_it.next();
String key = “entry_” +date_string+ “_” +code;
TimeEntryDTO entry = (TimeEntryDTO) entry_map.get(key);
String hours = “0”;
if (entry != null)
{
hours = “” + entry.getHours();
}

TextBoxPrimitive text_box = new TextBoxPrimitive(key);


267783 WS05.qxd 5/5/03 9:18 AM Page 24

24 RecordTimeServletjava

text_box.setInitialValue(hours);
text_box.setWidth(5);
table.setPrimitiveAt(row_ctr, col_ctr, text_box);
row_ctr++;
}
col_ctr++;
}

// add save button


SubmitPrimitive save_button = new SubmitPrimitive(“Save”);
save_button.setName(TimecardKey.SAVE_TIMECARD.getKeyText());
table.setPrimitiveAt(row_ctr, 1, save_button);

// add submit button


SubmitPrimitive submit_button = new SubmitPrimitive(“Submit”);
submit_button.setName(TimecardKey.SUBMIT_TIMECARD.getKeyText());
table.setPrimitiveAt(row_ctr, 2, submit_button);

FormPrimitive form = new FormPrimitive(“/Timecard/ Æ


RecordTimeServlet”, “rcif”);
form.addPrimitive(table);
page.addToBody(form);
}

return page;
}

private List getDatesInOrder(TimecardDTO timecard)


{
ArrayList dates = new ArrayList();
Calendar calendar = Calendar.getInstance();

// add dates from start to end


Date current = timecard.getStartDate();
Date end = timecard.getEndDate();
while (current.before(end))
{
String dbg = longFormat.format(current);
dates.add(current);
calendar.setTime(current);
calendar.add(Calendar.DAY_OF_MONTH, 1);
current = calendar.getTime();
}
dates.add(end);

return dates;
}

private List getChargeCodesInOrder(TimecardDTO timecard)


267783 WS05.qxd 5/5/03 9:18 AM Page 25

RecordTimeServletjava 25

{
ArrayList charge_codes = new ArrayList();

Iterator entries = timecard.getEntries();


while (entries.hasNext())
{
TimeEntryDTO entry = (TimeEntryDTO) entries.next();
String code =
entry.getClientName()+”.”+entry.getProjectName()+”.”+entry. Æ
getChargeCodeName();
if (!charge_codes.contains(code))
{
charge_codes.add(code);
}
}

Collections.sort(charge_codes);
return charge_codes;
}

/** Build a map of entries with date_chargecode as key*/


private Map getEntriesMap(TimecardDTO timecard)
{
Map entries_map = new HashMap();

Iterator entries = timecard.getEntries();


while (entries.hasNext())
{
TimeEntryDTO entry = (TimeEntryDTO) entries.next();
String date = this.keyFormat.format(entry.getDate());
String code =
entry.getClientName()+”.”+entry.getProjectName()+”.”+entry. Æ
getChargeCodeName();
String key = “entry_” +date+ “_” +code;
entries_map.put(key, entry);
}

return entries_map;
}

/** Extract hours from the request. */


private void updateTimecardFromRequest(TimecardDTO timecard, Æ
HttpServletRequest request)
{
Map entries_map = getEntriesMap(timecard);

Enumeration parameters = request.getParameterNames();


while (parameters.hasMoreElements())
{
String parameter = (String) parameters.nextElement();
267783 WS05.qxd 5/5/03 9:18 AM Page 26

26 RecordTimeServletjava

if (parameter.startsWith(“entry”))
{
String key = parameter;
String hours = request.getParameter(parameter);
TimeEntryDTO entry = (TimeEntryDTO) entries_map.get(key);
entry.setHours(Integer.parseInt(hours));
}
}
}
}
267783 WS06.qxd 5/5/03 9:18 AM Page 27

RecordTimeWorkflow-
SessionBean

RecordTimeWorkflowInt.java
RecordTimeWorkflowInt.java is the local interface for the RecordTimeWorkflow entity
bean. It defines the remotely accessible methods for the RecordTimeWorkflow entity
bean. Since RecordTimeWorkflow is a stateful session bean, each method assumes a
particular session, which involves a single user and a single current timecard. This
allows the getChargeCodes to have an empty parameter list. Again, notice that each
return type is either Java data type or a custom Data Transfer Object (DTO).

package com.wiley.compBooks.EJwithUML.TimeCardWorkflow;

import java.rmi.*;
import javax.ejb.*;
import java.util.*;
import com.wiley.compBooks.EJwithUML.TimeCardDomain.*;
import com.wiley.compBooks.EJwithUML.Dtos.*;
import com.wiley.compBooks.EJwithUML.Base.ApplicationExceptions.*;

/**
* The RecordTimeWorkflowInt is the interface that ties the Bean
* with the Remote interface to provide compile time type checking.
*/
public interface RecordTimeWorkflowInt

27
267783 WS06.qxd 5/5/03 9:18 AM Page 28

28 RecordTimeWorkflowSessionBean

{
/** Answers the current timecard. */
public TimecardDTO getCurrentTimecard() throws
DataCreateException,FatalApplicationException, RemoteException;

/** Marks the current timecard as closed and creates a new one. */
public void submitTimecard() throws DataCreateException,
FatalApplicationException,RemoteException;

/** Adds/Updates/modifies the entries of the current timecard. */


public void updateTimecard(TimecardDTO currentTimecard) throws Æ
DataUpdateException,DataNotFoundException,FatalApplicationException, Æ
RemoteException;

/**
* Answers a ClientDTO with client related information- projects
* and charge codes.
*/
public ClientDTO getClient(String clientName) throws Æ
DataNotFoundException,FatalApplicationException, RemoteException;

/**
* Answers a Collection of ClientDTOs with client related
* information- projects and charge codes.
*/
public Collection getAllClients() throws DataNotFoundException,
FatalApplicationException, RemoteException;
}

RecordTimeWorkflow.java
RecordTimeWorkflow.java is the remote EJB interface that inherits from RecordTime-
WorkflowInt and hence it has an empty body. This is in line with what we have set as
our implementation strategy for all of our EJBs. This is shown in Figure 03.

<<SessionRemote>>
RecordTimeWorkflow

+ getCurrentTimecard() : TimecardDTO
+ submitTimecard() : void
+ updateTimecard(currentTimecard : TimecardDTO) : void
+ getClient(name : String) : ClientDTO

Figure 03 Remote interface of the RecordTimeWorkflow session bean.


267783 WS06.qxd 5/5/03 9:18 AM Page 29

RecordTimeWorkflowSessionBean 29

package com.wiley.compBooks.EJwithUML.TimeCardWorkflow;

import javax.ejb.*;
import java.util.*;
import com.wiley.compBooks.EJwithUML.TimeCardDomain.*;
import com.wiley.compBooks.EJwithUML.Dtos.*;
import com.wiley.compBooks.EJwithUML.Base.ApplicationExceptions.*;

/**
* The RecordTimeWorkflow allows client objects to record their
* time. RecordTimeWorkflow is the remote interface through which
* clients access the underlying session bean.
*/
public interface RecordTimeWorkflow extends EJBObject, Æ
RecordTimeWorkflowInt
{
}

RecordTimeWorkflowHome.java
RecordTimeWorkflowHome.java contains the methods for creating RecordTimeWork-
flowHome session beans. The create method requires a username. This associates the
RecordTimeWorkflow session bean with a single user for the life of the session. This is
shown in Figure 04.

<<SessionHome>>
RecordTimeWorkflowHome

+ create(username : String) : RecordTimeWorkflow

Figure 04 Remote Home interface of the RecordTimeWorkflowHome session bean.

package com.wiley.compBooks.EJwithUML.TimeCardWorkflow;

import java.util.*;
import java.rmi.*;
import javax.ejb.*;
import com.wiley.compBooks.EJwithUML.Base.ApplicationExceptions.*;

/**
* The RecordTimeWorkflow allows client objects to record their time.
* RecordTimeWorkflowHome is the remote interface through which Æ
clients find
* and create the underlying session beans.
*/
public interface RecordTimeWorkflowHome extends EJBHome
267783 WS06.qxd 5/5/03 9:18 AM Page 30

30 RecordTimeWorkflowSessionBean

{
/** Answers a reference to the newly created Activity bean. */
public RecordTimeWorkflow create(String username) throws
RemoteException,
CreateException;
}

RecordTimeWorkflowBean.java
RecordTimeWorkflowBean.java is the implementation class for the RecordTimeWork-
flow session bean. Most of this code should be somewhere between familiar and
monotonous, by this point. However, there is one new wrinkle, as the ejbCreate
method finds a User entity bean based on the username parameter. This bean reference
is kept for the duration of the stateful session. The RecordTimeWorkflow session bean
wraps the data for a timecard into a custom TimecardDTO object.

package com.wiley.compBooks.EJwithUML.TimeCardWorkflow;

import com.wiley.compBooks.EJwithUML.Dtos.*;
import com.wiley.compBooks.EJwithUML.TimeCardDomain.*;
import com.wiley.compBooks.EJwithUML.Base.ApplicationExceptions.*;
import com.wiley.compBooks.EJwithUML.Base.DateUtil;
import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import java.util.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;

/**
* The RecordTimeWorkflow allows client objects to record their time.
* RecordTimeWorkflowBean is the actual session bean implementation.
*/
public class RecordTimeWorkflowBean extends BasicSessionBean
{
private UserLocal user;

public void ejbCreate(String username) throws CreateException


{
try
{
System.out.println(“creating RecordTimeWorkflowBean with user -” Æ
+ username);
Context initialContext = getInitialContext();
UserLocalHome userHome = (UserLocalHome)initialContext.lookup(
EjbReferenceNames. Æ
USER_HOME);
Collection users = userHome.findByUserName(username);
Iterator userIterator = users.iterator();
267783 WS06.qxd 5/5/03 9:18 AM Page 31

RecordTimeWorkflowSessionBean 31

if (userIterator.hasNext())
{
this.user = (UserLocal) userIterator.next();
}
System.out.println(“done creating RecordTimeWorkflowBean with user
-” +
username);
}
catch (NamingException e)
{
throw new CreateException(“User Bean Not Found”);
}
catch (FinderException e)
{
throw new CreateException(“User(“ + username + “) Not Found”);
}
}

public void ejbPostCreate(String username)


{
}

/** Answers the current timecard. If first time, creates one. */


public TimecardDTO getCurrentTimecard() throws DataCreateException,
FatalApplicationException, RemoteException
{
try
{
System.out.println(“in getCurrentTimecard().”);
TimecardLocal timecard = user.getCurrentTimecard();
if (timecard == null)
{
// creates for the first time
timecard = createTimecard(timecard);
}
TimecardDTO tcDTO = new TimecardDTO(new Date(timecard.getStartDate()),
new Date(timecard.getEndDate()));
Collection timeEntries = timecard.getTimeEntries();
Iterator timeEntryIterator = timeEntries.iterator();
System.out.println(“total entries#” + timeEntries.size());
while(timeEntryIterator.hasNext())
{
TimeEntryLocal timeEntry = (TimeEntryLocal) Æ
timeEntryIterator.next();
ChargeCodeLocal chargeCode = (ChargeCodeLocal) Æ
timeEntry.getChargeCode();
TimeEntryDTO timeEntryDTO = new TimeEntryDTO(
((TimeEntryPK)timeEntry.getPrimaryKey()).id,
chargeCode.getProject().getClient().getName(),
chargeCode.getName(), chargeCode.getProject().getName(),
267783 WS06.qxd 5/5/03 9:18 AM Page 32

32 RecordTimeWorkflowSessionBean

timeEntry.getHours(), timeEntry.getDate());
tcDTO.addEntry(timeEntryDTO);
}
System.out.println(tcDTO);
return tcDTO;
}
catch(InvalidDataException e)
{
throw new DataCreateException(Origin.TIMECARD_WORKFLOW, e,
“failed to retrieve current Æ
timecard.”);
}
}

/** Marks the current timecard as closed and creates a new one. */
public void submitTimecard() throws DataCreateException,
FatalApplicationException, RemoteException
{
System.out.println(“in submitTimecard().”);
TimecardLocal currentTimecard = user.getCurrentTimecard();
createTimecard(currentTimecard);
}

/** Adds/Updates/modifies the entries of the current timecard. */


public void updateTimecard(TimecardDTO tcDTO) throws Æ
DataUpdateException,
DataNotFoundException, Æ
FatalApplicationException
{
try
{
System.out.println(“in getUpdateTimecard().”);
Context initialContext = getInitialContext();
TimeEntryLocalHome tehome = Æ
(TimeEntryLocalHome)initialContext.lookup(
EjbReferenceNames. Æ
TIME_ENTRY_HOME);
ChargeCodeLocalHome cchome = (ChargeCodeLocalHome) Æ
initialContext.lookup(
EjbReferenceNames. Æ
CHARGECODE_HOME);
Iterator teIterator = tcDTO.getEntries();
System.out.println(“total entries#” + tcDTO.getTotalEntries());
while(teIterator.hasNext())
{
TimeEntryDTO entryDTO = (TimeEntryDTO)teIterator.next();
TimeEntryLocal tentry = null;
ChargeCodeLocal ccode = null;
Collection ccodes = cchome.findByName(entryDTO. Æ
getProjectName(),
267783 WS06.qxd 5/5/03 9:18 AM Page 33

RecordTimeWorkflowSessionBean 33

entryDTO. Æ
getChargeCodeName());
if (ccodes.size() == 1)
{
// we have single hit
ccode = (ChargeCodeLocal) ccodes.iterator().next();
}
else
{
//we have multiple hits; we need to narrow it down to 1
Iterator ccIterator = ccodes.iterator();
while(ccIterator.hasNext())
{
ChargeCodeLocal nextCcode = (ChargeCodeLocal) Æ
ccIterator.next();
if (nextCcode.getProject().getClient().getName().equals(
entryDTO.getClientName()))
{
ccode = nextCcode;
break;
}
}
if (ccode == null)
{
System.out.println(“could not find the charge code. Æ
cannot update/create - “
+ entryDTO);
continue;
}
}
if (entryDTO.isUpdated())
{
try
{
tentry = (TimeEntryLocal) tehome.findByPrimaryKey(new
TimeEntryPK Æ
(entryDTO.getId()));
/* makes sure that the entry belongs to the right timecard*/
if (!tentry.getTimecard().getPrimaryKey().equals(
user.getCurrentTimecard().getPrimaryKey()))
{
throw new DataUpdateException(Origin.TIMECARD_WORKFLOW,
“Duplicate Time Entry-” + Æ
entryDTO.toString());
}
System.out.println(“updating entry-” + entryDTO);
tentry.setDate(entryDTO.getDate());
tentry.setHours(entryDTO.getHours());
tentry.setChargeCode(ccode);
}
267783 WS06.qxd 5/5/03 9:18 AM Page 34

34 RecordTimeWorkflowSessionBean

catch(FinderException exception)
{
throw new DataUpdateException(Origin.TIMECARD_WORKFLOW,
“Marked as an update, but no entry found-” + Æ
entryDTO.toString());
}
}
else if (entryDTO.isNew())
{
// new entry- we need to add it; new entry has partial key; we
// need to add the timecard id to it. see TimeEntryDTO for
// more details.
String newId =((TimecardPK)user.getCurrentTimecard Æ
().getPrimaryKey()).id
+ “-” + entryDTO.getId();
System.out.println(“adding a new entry-” + entryDTO);
System.out.println(“actual id=” + newId);
tehome.create(newId,entryDTO.getDate(), entryDTO.getHours(),
ccode, user.getCurrentTimecard());
}
}
System.out.println(“total entries#” +
user.getCurrentTimecard(). Æ
getTimeEntries().size());
System.out.println(“done getUpdateTimecard().”);
}
catch(NamingException exception)
{
// invalid charge code
throw new FatalApplicationException(Origin.TIMECARD_WORKFLOW, Æ
exception,
“ChargeCode/TimeEntry Bean Not Æ
Found”);
}
catch(FinderException exception)
{
// invalid charge code
throw new DataNotFoundException(Origin.TIMECARD_WORKFLOW, exception,
“invalid charge code, failed to update Æ
timecard.” );
}
catch (CreateException e)
{
throw new DataUpdateException(Origin.TIMECARD_WORKFLOW, e,
“Failed to update timecard.”);
}

/**
267783 WS06.qxd 5/5/03 9:18 AM Page 35

RecordTimeWorkflowSessionBean 35

* Answers a ClientDTO with client related information- projects and


* charge codes.
*/
public ClientDTO getClient(String clientName) throws Æ
DataNotFoundException,
Æ
FatalApplicationException
{
try
{
System.out.println(“in getClient().”);
Context initialContext = getInitialContext();
ClientLocalHome chome = (ClientLocalHome)initialContext.lookup(
Æ
EjbReferenceNames.CLIENT_HOME);
Collection clients = chome.findByName(clientName);
Iterator clientIterator = clients.iterator();
ClientLocal client = null;
if (clientIterator.hasNext())
{
//should be unique; so we only get to look for one.
client = (ClientLocal) clientIterator.next();
}
ClientDTO cDTO = new ClientDTO(client.getName());
extractClientInfo(client, cDTO);
System.out.println(“done getClient().”);
return cDTO;
}
catch (NamingException exception)
{
// invalid charge code
throw new FatalApplicationException(Origin.TIMECARD_WORKFLOW, Æ
exception,
“Client Bean Not Found”);
}
catch (FinderException exception)
{
throw new DataNotFoundException(Origin.TIMECARD_WORKFLOW, Æ
exception,
“client(“ + clientName + “) not found.” );
}
}

/**
* Answers a Collection of ClientDTOs with client related information-
* projects and charge codes.
*/
public Collection getAllClients() throws DataNotFoundException,
FatalApplicationException, Æ
RemoteException
267783 WS06.qxd 5/5/03 9:18 AM Page 36

36 RecordTimeWorkflowSessionBean

{
try
{
System.out.println(“in getAllClients().”);
Context initialContext = getInitialContext();
ClientLocalHome chome = (ClientLocalHome)initialContext.lookup(
Æ
EjbReferenceNames.CLIENT_HOME);
Collection clients = chome.findAll();
Iterator clientIterator = clients.iterator();
Collection clientDtos = new ArrayList();
ClientLocal client = null;
while(clientIterator.hasNext())
{
client = (ClientLocal) clientIterator.next();
ClientDTO cDTO = new ClientDTO(client.getName());
extractClientInfo(client, cDTO);
clientDtos.add(cDTO);
}
System.out.println(“done getAllClients().”);
return clientDtos;
}
catch (NamingException exception)
{
// invalid charge code
throw new FatalApplicationException(Origin.TIMECARD_WORKFLOW, Æ
exception,
“Client Bean Not Found”);
}
catch (FinderException exception)
{
throw new DataNotFoundException(Origin.TIMECARD_WORKFLOW, Æ
exception,
“no client found.” );
}
}

private void extractClientInfo(ClientLocal client, ClientDTO cDTO)


{
System.out.println(“in extractClientInfo().”);
Collection projects = client.getProjects();
Iterator projectIterator = projects.iterator();
while(projectIterator.hasNext())
{
ProjectLocal project = (ProjectLocal) projectIterator.next();
ProjectDTO pDTO = new ProjectDTO(project.getName());
Collection chargeCodes = project.getChargeCodes();
Iterator ccIterator = chargeCodes.iterator();
while(ccIterator.hasNext())
{
267783 WS06.qxd 5/5/03 9:18 AM Page 37

RecordTimeWorkflowSessionBean 37

ChargeCodeLocal chargeCode = (ChargeCodeLocal) Æ


ccIterator.next();
pDTO.addChargeCode(chargeCode.getName());
}
cDTO.addProject(pDTO);
System.out.println(“done extractClientInfo().”);
}
}

private TimecardLocal createTimecard(TimecardLocal currentTimecard)


throws DataCreateException, FatalApplicationException, Æ
RemoteException
{
try
{
System.out.println(“creating a new Timecard.”);
/*
* closes the current timecard by creating a new one.
* timecard id = userid + “-”+ year+ “-”+ “week”;
* Timecard starts on Monday and ends on Sunday. Duration of each Æ
timecard
* is 7 days.
*/
Date startDate = null;
if (currentTimecard == null)
{
// first timecard
startDate = DateUtil.getCurrentWeekMonday(new Date());
}
else
{
startDate = DateUtil.getNextWeekMonday(new Æ
Date(currentTimecard.getStartDate()));
}
String id = ((UserPK)user.getPrimaryKey()).id + “-” +
DateUtil.getCurrentYear(startDate) + “-” +
DateUtil.getCurrentWeek(startDate);
Date endDate = DateUtil.getCurrentWeekSunday(startDate);
System.out.println(“startDate= “ + Æ
DateUtil.toDateString(startDate) +
“ endDate=” + DateUtil.toDateString(endDate));
Context initialContext = getInitialContext();
TimecardLocalHome tchome = (TimecardLocalHome) Æ
initialContext.lookup(
EjbReferenceNames. Æ
TIMECARD_HOME);
TimecardLocal nextTimecard = tchome.create(id, startDate, Æ
endDate, true,
user);
//makes the current timecard to be not current, and makes the new
267783 WS06.qxd 5/5/03 9:18 AM Page 38

38 RecordTimeWorkflowSessionBean

//one to be current.
if(user.getCurrentTimecard()!= null)
{
user.getCurrentTimecard().setIsCurrent(false);
}
user.setCurrentTimecard(nextTimecard);
System.out.println(“done creating a new Timecard.”);
return nextTimecard;
}
catch (NamingException e)
{
throw new FatalApplicationException(Origin.TIMECARD_WORKFLOW, e,
“Timecard Bean Not Found”);
}
catch (CreateException e)
{
throw new DataCreateException(Origin.TIMECARD_WORKFLOW, e,
“Failed to create timecard.”);
}
}
}
267783 WS07.qxd 5/5/03 9:18 AM Page 39

SelectChargeCodeServletjava

SelectChargeCodeServlet.java
The SelectChargeCodeServlet uses the RecordTimeWorkflow to get a collection of
charge codes that are valid for the system. It uses TablePrimitive, TextPrimitive, and
LinkPrimitive to build a list of charge codes with an associated “Add” link for each
charge code. When the user clicks on an “Add” link, RecordTimeServlet uses the
request parameters to identify the correct charge code to add to the timecard.

package com.wiley.compBooks.EJwithUML.TimecardUI;

import javax.servlet.http.*;
import javax.servlet.*;

import javax.naming.*;
import javax.ejb.*;
import java.rmi.*;
import javax.rmi.PortableRemoteObject;

import java.io.*;
import java.util.*;
import java.text.*;

import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.Core.*;

39
267783 WS07.qxd 5/5/03 9:18 AM Page 40

40 SelectChargeCodeServletjava

import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.FormPrimitives.*;
import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.Layout.*;
import com.wiley.compBooks.EJwithUML.Base.HtmlPrimitives.ContentElements.*;
import com.wiley.compBooks.EJwithUML.TimeCardWorkflow.*;
import com.wiley.compBooks.EJwithUML.TimeCardDomain.*;
import com.wiley.compBooks.EJwithUML.TimecardProducers.*;
import com.wiley.compBooks.EJwithUML.Dtos.*;
import com.wiley.compBooks.EJwithUML.Base.EjbUtil.*;
import com.wiley.compBooks.EJwithUML.Base.ApplicationExceptions.*;

/**
* The RecordTimeServlet uses the TimecardWorkflow and
* HtmlProduction packages to create the formatted HTML
* to build a charge code selection grid.
*/
public class SelectChargeCodeServlet extends BasicTimecardServlet
{
private RecordTimeWorkflowHome rtwhome = null;

/** Overrides method from HttpServlet. doGet is called by the Æ


servlet engine. */
public void doGet(HttpServletRequest request, HttpServletResponse Æ
response) throws ServletException, IOException
{
doPost(request, response);
}

/** Overrides method from HttpServlet. doPost is called by the Æ


servlet engine. */
public void doPost(HttpServletRequest request, HttpServletResponse Æ
response) throws ServletException, IOException
{
try
{
HttpSession session = request.getSession();
String username = (String)
session.getAttribute(TimecardKey.USERNAME.getKeyText());

PagePrimitive page = new TimecardPageProducer(“Select a Æ


Charge Code”);
ParagraphPrimitive page_title = new ParagraphPrimitive Æ
(TimecardStyle.IMPORTANT_TEXT, “Select a charge code from the list below”);
page.addToBody(page_title);

Iterator clients = getClients(username);


TablePrimitive table = new TablePrimitive();
table.setStyle(TimecardStyle.CHARGE_CODE_SELECTION_TABLE);
table.setStyleForCells(TimecardStyle.CHARGE_CODE_SELECTION_CELLS);
page.addToBody(table);

int row_ctr = 0;
267783 WS07.qxd 5/5/03 9:18 AM Page 41

SelectChargeCodeServletjava 41

table.setPrimitiveAt(row_ctr, 0, new Æ
SpanPrimitive(TimecardStyle.IMPORTANT_TEXT, “Client”));
table.setPrimitiveAt(row_ctr, 1, new Æ
SpanPrimitive(TimecardStyle.IMPORTANT_TEXT, “Project”));
table.setPrimitiveAt(row_ctr, 2, new Æ
SpanPrimitive(TimecardStyle.IMPORTANT_TEXT, “Code”));
table.setPrimitiveAt(row_ctr, 3, new Æ
SpanPrimitive(TimecardStyle.IMPORTANT_TEXT, “Action”));
row_ctr++;

while (clients.hasNext())
{
ClientDTO client = (ClientDTO) clients.next();
Iterator projects = client.getProjects();
while (projects.hasNext())
{
ProjectDTO project = (ProjectDTO) projects.next();
Iterator codes = project.getChargeCodes();
while (codes.hasNext())
{
String code = (String) codes.next();
String url = “/Timecard/RecordTimeServlet?” Æ
+TimecardKey.CLIENT.getKeyText()+”=” +client.getName()+
“&” +TimecardKey.PROJECT.getKeyText()+”=” Æ
+project.getName()+ “&”+ TimecardKey.CODE.getKeyText()+”=” +code;
TextPrimitive client_text = new Æ
TextPrimitive(client.getName());
TextPrimitive project_text = new Æ
TextPrimitive(project.getName());
TextPrimitive code_text = new TextPrimitive(code);
TextPrimitive link_text = new TextPrimitive(“Add”);
LinkPrimitive add_link = new LinkPrimitive(url);
add_link.addText(link_text);

table.setPrimitiveAt(row_ctr, 0, client_text);
table.setPrimitiveAt(row_ctr, 1, project_text);
table.setPrimitiveAt(row_ctr, 2, code_text);
table.setPrimitiveAt(row_ctr, 3, add_link);
row_ctr++;
}
}
}

// write page to response


StringBuffer buffer = new StringBuffer();
page.buildContent(buffer);
response.getWriter().println(buffer.toString());
response.getWriter().flush();
267783 WS07.qxd 5/5/03 9:18 AM Page 42

42 SelectChargeCodeServletjava

response.getWriter().close();
}
catch (Exception e)
{
throw new ServletException(e);
}
}

private Iterator getClients(String username) throws


ApplicationException, RemoteException, NamingException, CreateException
{
if (rtwhome == null)
{
// Get workflow and timecard
Context initial = new InitialContext();
Object objref = initial.lookup(EjbReferenceNames. Æ
RECORD_TIME_WORKFLOW_HOME);
rtwhome =
(RecordTimeWorkflowHome)PortableRemoteObject.narrow(objref, Æ
RecordTimeWorkflowHome.class);
}

RecordTimeWorkflow rtwf = rtwhome.create(username);


Collection clients = rtwf.getAllClients();
return clients.iterator();
}
}
267783 WS08.qxd 5/5/03 9:19 AM Page 43

Visual Glossary

The following glossary shows how several important object-oriented concepts are
shown in the UML and how they can be implemented in Java. Each section describes a
concept, provides a sample UML diagram that uses the concept, implements the UML
in Java, and offers some guidance on the proper use of the concept.

Generalization
One or more subclasses may share the attributes and behavior that are defined for the
base class. There are two ways to describe this relationship in proper object-oriented
terminology. First, a class inherits all of the attributes and behaviors from a superclass
or base class. From the opposite perspective, the superclass is a generalization of the
attributes and behaviors that are common to all of its subclasses. In UML, the relationship
is described as a generalization and is denoted by a solid line with a hollow arrow
pointing to the base class.

43
267783 WS08.qxd 5/5/03 9:19 AM Page 44

44 Visual Glossary

Vehicle

+ go() : String
+ startEngine() : void
+ stopEngine() : void
+ isEngineOn() : boolean

Car Truck

+ go() : String + go() : String

Figure VG.1 Generalization example.

UML Example
Consider a brief example of generalization. Vehicle is a generalization of both Car and
Truck. The two subclasses, Truck and Car, inherit all of the attributes and behavior
from the base class. Figure VG.1 shows the two subclasses, with generalization arrows
pointing to the base class. In this case, there is no default go behavior for vehicles, so
the base class must be abstract. Each concrete subclass of Vehicle must provide an
implementation of the go method. Each concrete subclass may accept the default
behavior for startEngine, stopEngine, and isEngineOn. If the default implementation is
inappropriate, the subclass may override the default implementation by providing its
own implementation.
In UML, rendering the abstract class name in italics indicates that the class is
abstract. Showing a method in both the base class and in the subclass indicates that the
subclass overrides that method.

Java Example
The following Java files show how the UML model in Figure VG.1 can be implemented
in Java.

Vehicle.java
Vehicle.java is the abstract base class in Figure VG.1. This is reflected in the source
code, as the class and the go method are both abstract. The other methods have imple-
mentations, but are not final, so they may be overridden by subclasses.

/**
* The Vehicle class contains the data and behavior that
267783 WS08.qxd 5/5/03 9:19 AM Page 45

Visual Glossary 45

* is common to all Vehicles.


*/
public abstract class Vehicle
{
private boolean engineStarted;

/** Answers the noise made when the Vehicle goes.


Must be overridden by all concrete implementations
of Vehicle. */
public abstract String go();

/** Starts engine. */


public void startEngine()
{
this.engineStarted = true;
}

/** Stops engine. */


public void stopEngine()
{
this.engineStarted = false;
}

/** Answers true if engine is started. */


public boolean isEngineOn()
{
return this.engineStarted;
}
}

Car.java
Car.java is a subclass of Vehicle, which in Java is indicated by the reserved word
“extends.” Car overrides the go method and uses the base class implementation of the
isEngineOn method.

/**
* The Car class inherits from Vehicle and overrides the go method.
* It encapsulates all data and behavior that is specific to Cars.
*/
public class Car extends Vehicle
{
/** Answers the noise made by the Car when it goes. */
public String go()
{
if (this.isEngineOn())
{
return “Vroom”;
267783 WS08.qxd 5/5/03 9:19 AM Page 46

46 Visual Glossary

}
else
{
return “...”;
}
}
}

Truck.java
Truck.java is a subclass of Vehicle, which in Java is indicated by the reserved word
“extends.” Truck overrides the go method and uses the base class implementation of
the isEngineOn method. Truck is almost identical to Car, with a different implementation
of the go method.

/**
* The Truck class inherits from Vehicle and overrides the go method.
* It encapsulates all data and behavior that is specific to Trucks.
*/
public class Truck extends Vehicle
{
/** Answers the noise made by the Truck when it goes. */
public String go()
{
if (this.isEngineOn())
{
return “Rumble”;
}
else
{
return “...”;
}
}
}

Guidelines
It is extremely important for the generalization relationship to be an accurate descrip-
tion of the underlying reality that you are modeling. Each subclass must really be a
refinement of the superclass. Do not subclass a class just to get useful behavior or
attributes. Doing so makes the system significantly more difficult to understand, and
may result in strange errors as the system evolves.
267783 WS08.qxd 5/5/03 9:19 AM Page 47

Visual Glossary 47

Realization
A class realizes an interface by implementing each method that is defined in the inter-
face. By realizing the interface, the class is promising to make the interface real. In
UML, the realization relationship is denoted by a dashed line, with a hollow arrow
pointing to the interface.

UML Example
Continuing the earlier example, some Vehicles can carry cargo, some cannot. Also,
some classes that are not “normal” vehicles may also carry cargo. So, rather than intro-
ducing a separate subclass for all cargo-carrying vehicles, we introduce an interface,
ICargoTransport. Our design allows any class to realize the ICargoTransport by
providing an implementation for the loadCargo method. Figure VG.2 shows Truck
realizing the ICargoTransport interface, while Car does not.

Java Example
The following Java files show how the UML model in Figure VG.2 can be implemented
in Java. Only the files that have changed from the generalization example are shown.

Vehicle
<<Interface>>
+ go() : String ICargoTransport
+ startEngine() : void
+ stopEngine() : void + loadCargo() : void
+ isEngineOn() : boolean

Car Truck

+ go() : String + go() : String


+ loadCargo() : void

Figure VG.2 Realization example.


267783 WS08.qxd 5/5/03 9:19 AM Page 48

48 Visual Glossary

Truck.java
Truck.java is a subclass of Vehicle, which in Java is indicated by the reserved word
“extends.” Truck overrides the go method and uses the base class implementation of
the isEngineOn method. Truck also realizes the ICargoTransport interface, as indicated
by the “implements” reserved word in the class definition.

/**
* The Truck class inherits from Vehicle, and overrides the go
* method. It encapsulates all data and behavior that is specific to
* Trucks.
*/
public class Truck extends Vehicle implements ICargoTransport
{
/** Answers the noise made by the Truck when it goes. */
public String go()
{
if (this.isEngineOn())
{
return “Rumble”;
}
else
{
return “...”;
}
}

/** Adds cargo to this Truck.*/


public void loadCargo()
{
}
}

ICargoTransport.java
ICargoTransport.java simply defines the name and signature for the loadCargo
method. As an interface, it is precluded from providing an implementation.

/**
* The ICargoTransport interface defines the methods
* that must be implemented by all classes that
* transport cargo.
*/
public interface ICargoTransport
{
267783 WS08.qxd 5/5/03 9:19 AM Page 49

Visual Glossary 49

/** Loads cargo for transport. */


public void loadCargo();
}

Guidelines
All of the methods in an interface must combine to describe a coherent responsibility.

Association
An association is a long-term relationship between objects. In an association, an object
keeps a reference to another object, and can call the object’s methods as it needs them.
Real life is replete with association relationships. Consider a person with his or her
own automobile. As long as he or she remembers where it is parked, the car will let the
person in to drive to his or her destination. In the UML, a solid line between the two
classes represents an association.
In some cases, an object may instantiate another object and keep a reference to it for
future use. An object may also receive an object as a parameter to a configuration
method and keep a reference to the object.

UML Example
Consider an association relationship in which each Person object knows about zero or
more Vehicle objects. Figure VG.3 shows this relationship in a class diagram. The rela-
tionship is read as “every Person object is associated with zero or more Vehicle
objects,” and “every Vehicle object is associated with one or more Person objects.” It
may help to think of this as a “knows-about-a” relationship, as in “each Person object
knows about some Vehicle objects.”

Vehicle
<<Interface>>
Person ICargoTransport
+ go() : String
+ startEngine() : void
+ addVehicle(v : Vehicle) : void 1..* 0..*
+ stopEngine() : void + loadCargo() : void
+ isEngineOn() : boolean

Car Truck

+ go() : String + go() : String


+ loadCargo() : void

Figure VG.3 Association example.


267783 WS08.qxd 5/5/03 9:19 AM Page 50

50 Visual Glossary

Java Example
Person.java shows how the association relationship shown in Figure VG.3 between
Person and Vehicle can be implemented in Java. Each reference to a Vehicle object is
kept in a Vector.

Person.java
The Person class simply holds the vehicles for a person.

import java.util.*;

/**
* The Person class contains all data and logic for a person
* in the system.
*/
public class Person
{
public Vector vehicles = new Vector();

/** Adds a vehicle to this person. */


public void addVehicle(Vehicle v)
{
this.vehicles.addElement(v);
}
}

Guidelines
Association is the default long-term relationship between objects. If you are in doubt as
to which long-term relationship to use, use association.

Aggregation
Aggregation indicates a long-term relationship, with the additional restriction that
some of the objects are part of another object. It is this whole-part nature of the rela-
tionship that distinguishes aggregation from association.

UML Example
To continue the example, each Vehicle object may contain zero or one Engine objects.
There is a clear whole-part relationship, as the engine is part of the car or truck. Figure
VG.4 shows a modified association from Vehicle to Engine, with the hollow diamond
at the Vehicle indicating aggregation. The hollow diamond is always drawn next to the
enclosing whole.
267783 WS08.qxd 5/5/03 9:19 AM Page 51

Visual Glossary 51

Engine

+ start() : void
+ stop() : void
Vehicle + isOn() : boolean
0..1
Person 1
+ go() : String
+ startEngine() : void <<Interface>>
+ addVehicle(v : Vehicle) : void 1..* 0..* ICargoTransport
+ stopEngine() : void
+ isEngineOn() : boolean
+ loadCargo() : void

Car Truck

+ go() : String + go() : String


+ loadCargo() : void

Figure VG.4 Aggregation example.

Java Example
The following Java files show how the UML model in Figure VG.4 can be implemented
in Java. Only the files that have changed from the previous running example are
shown.

Vehicle.java
Vehicle no longer determines whether it is running or not. Instead, this behavior is
delegated to an Engine object.

/**
* The Vehicle class contains the data and behavior that
* is common to all Vehicles.
*/
public abstract class Vehicle
{
private Engine engine;

/** Sets the engine */


public void setEngine(Engine e)
{
this.engine = e;
}

/** Answers the noise made when the Vehicle goes.


Must be overridden by all concrete implementations
of Vehicle. */
267783 WS08.qxd 5/5/03 9:19 AM Page 52

52 Visual Glossary

public abstract String go();

/** Starts engine. */


public void startEngine()
{
if (this.engine != null)
{
this.engine.start();
}
}

/** Stops engine. */


public void stopEngine()
{
if (this.engine != null)
{
this.engine.stop();
}

/** Answers true if engine is started. */


public boolean isEngineOn()
{
if (this.engine != null)
{
return this.engine.isOn();
}

return false;
}
}

Engine.java
Engine.java provides very simple behavior for starting, stopping, and checking the
current value.

/**
* The Engine class contains the data and behavior for all engines
* for use with Vehicles.
*/
public class Engine
{
private boolean on;

/** Starts this engine. */


267783 WS08.qxd 5/5/03 9:19 AM Page 53

Visual Glossary 53

public void start()


{
this.on = true;
}

/** Stops this engine. */


public void stop()
{
this.on = false;
}

/** Answers true if the engine is running. */


public boolean isOn()
{
return this.on;
}
}

Guidelines
Aggregation requires a clear whole-part relationship. Any uncertainty about the need
for aggregation or ambiguity over which object is the whole and which is the part
should lead you to use association instead.

Composition
Composition is an even stronger relationship, with one object essentially owning the
other object or objects. The subordinate objects are created when the whole is created,
and are destroyed when the whole is destroyed. Also, an object cannot play the role of
a subordinate part in two composition relationships.

UML Example
Every engine contains many wheels, cogs, and gears that are integral and indivisible
parts of the greater whole. Figure VG.5 shows that each Engine object contains zero or
many Cog objects. The filled-in diamond next to the enclosing class indicates the com-
position relationship.

Java Example
The following Java file shows how the UML model in Figure VG.5 can be implemented
in Java. Only the files that have changed from the previous running example are
shown.
267783 WS08.qxd 5/5/03 9:19 AM Page 54

54 Visual Glossary

Vehicle
Person <<Interface>>
+ go() : String
ICargoTransport
+ startEngine() : void
+ addVehicle(v : Vehicle) : void 1..* 0..*
+ stopEngine() : void
+ loadCargo() : void
+ isEngineOn() : boolean
1

0..1

Engine

+ start() : void
Car Truck
+ stop() : void
+ isOn() : boolean + go() : String
+ go() : String
1 + loadCargo() : void

Cog

Figure VG.5 Composition example.

Engine.java
The Cog objects are created when the Engine is created, and become eligible for
garbage collection along with their enclosing Engine.

import java.util.*;

/**
* The Engine class contains the data and behavior for all engines
* for use with Vehicles.
*/
public class Engine
{
private boolean on;
private Vector cogs = new Vector();

public Engine()
{
this.cogs.addElement(new Cog());
this.cogs.addElement(new Cog());
}

/** Starts this engine. */


public void start()
{
267783 WS08.qxd 5/5/03 9:19 AM Page 55

Visual Glossary 55

this.on = true;
}

/** Stops this engine. */


public void stop()
{
this.on = false;
}

/** Answers true if the engine is running. */


public boolean isOn()
{
return this.on;
}
}

Guidelines
As with aggregation, when in doubt, do not use composition.

Dependency
Objects often need to use another object. An object may receive a reference as a param-
eter to a method, or it may create the object, use it, and lose it before the end of the cur-
rent method. The key idea is that the dependent object acquires, uses, and forgets the
object within a single method.

UML Example
Continuing the example, people use gas pumps to get gas, but most people do not keep
track of every pump that they have used. The Person object receives a reference to a
GasPump object as a parameter to the purchaseGas method. The reference is used
within the method; it is not kept. The resulting dependency relationship can be seen as
the dashed line from Person to GasPump in Figure VG.6.

Java Example
Person.java shows how the dependency relationship between Person and GasPump
can be implemented in Java.
267783 WS08.qxd 5/5/03 9:19 AM Page 56

56 Visual Glossary

Vehicle
Person <<Interface>>
+ go() : String
ICargoTransport
+ startEngine() : void
+ addVehicle(v : Vehicle) : void 1..* 0..*
+ stopEngine() : void
+ purchaseGas(pump : GasPump) : void + loadCargo() : void
+ isEngineOn() : boolean
1

0..1

Engine
GasPump
+ start() : void Car
+ stop() : void Truck
+ isOn() : boolean + go() : String
+ go() : String
1 + loadCargo() : void

Cog

Figure VG.6 Dependency example.

Person.java
Now, the Person class has a purchaseGas method that accepts a reference to a GasPump
object as a parameter.

import java.util.*;

/**
* The Person class contains all data and logic for a person
* in the system.
*/
public class Person
{
public Vector vehicles = new Vector();

/** Adds a vehicle to this person. */


public void addVehicle(Vehicle v)
{
this.vehicles.addElement(v);
}

public void purchaseGas(GasPump pump)


{
// use pump
// forget about pump
}
}
267783 WS08.qxd 5/5/03 9:19 AM Page 57

Visual Glossary 57

Guidelines
Dependency should be used whenever an object is used and forgotten within a single
method.
267783 WS08.qxd 5/5/03 9:19 AM Page 58

You might also like