diaries, triumphs, failures, and rants
- All
- Animals
- Books
- Chess
- Cigars and the Man-Grill
- Collaboration
- Doctor Who
- General
- Internet
- iPhone
- Java
- LDAP
- mac
- oneLiners
- onThisDay
- slamd
- Star Trek
- Sun
- Travel
SLAMD wth Struts2 progress report: annotations instead of struts.xml
Added breadcrumbs to the SLAMD administrative interface.[Read More]Posted at 11:52AM Mar 30, 2009 by tgardner in slamd | Comments[0]
Locales and Resource bundles introduced to SLAMD
Locales added to SLAMD.[Read More]Posted at 09:35PM Mar 20, 2009 by tgardner in slamd | Comments[0]
SLAMD: job class lists using Struts tags & OGNL
SLAMD version 2 constructs HTML in a huge Java servlet (com.slamd.admin.AdminServlet). One of my first tasks for SLAMD3 is to de-couple the HTML generation from the Java code so that SLAMD will be more flexible in HTML generation. The method I use is based on MVC using Struts2. Hopefully, I'll be able to detail my progress as an ongoing series of blog entries - in my spare time.
The first page I converted was the "Schedule a New Job" page. The way this page works in SLAMD2 is as follows: the com.slamd.admin.AdminServlet class examines parameters passed in the servlet request. If the "job_class" parameter (the String is a static final in com.slamd.common.Constants) is not present in the URL, the servlet constructs a categorized list of jobs and displays them as links in an un-ordered list. The underlying code creates a two dimensional array of com.slamd.job.JobClass objects and constructs HTML from the array:
public class AdminServlet
{
...
void handleScheduleJob(...)
{
JobClass[][] categorizedJobClasses =
slamdServer.getCategorizedJobClasses();
// construct HTML
}
}
To convert this to an MVC model in Struts2, I constructed a JSP called scheduleJob.jsp and mapped it to an Action in the struts.xml file like so:
<action name="ScheduleJob"
class="com.slamd.struts2.actions.ScheduleJobAction">
<interceptor-ref name="slamdStack"/>
<result name="success">/jsps/scheduleJob.jsp</result>
<result name="error">/jsps/error.jsp</result>
</action>
The action definition for "ScheduleJob" causes the dispatcher to route a URL like
http://hostname:port/slamd/ScheduleJob.actionthrough the interceptor stack "slamdStack", and then to the com.slamd.struts2.action.ScheduleJobAction object. the method "execute()" in actions must return a String indicating the result of the action execution. If the String returned by "execute()" is "success", then the view "scheduleJob.jsp" is the view, if "execute()" returns the String "error", then "error.jsp" is the view. ScheduleJobAction sets a field "jobClassName" to "noJob" (com.slamd.common.Constants.NO_JOB_PARAM) if no job parameter was present in the URL, or the job class name otherwise. This is the first use case: create the job class list when the "job_class" parameter is not part of the URL that is sent to the com.slamd.struts2.actions.ScheduleJobAction action.
A simple way to make construction of the job class list a little easier was to map the two dimensional array of JobClass objects to a Collection (java.util.Map) like so:
public class JobClassArrayHelper<T extends JobClass>
{
public Map<String,List<T>> convert2dArrayToMap(T[][] a)
{
Map<String,List<T>> map = null;
if(a != null)
{
map = new HashMap<String,List<T>>();
for(int i = 0; i < a.length; ++i)
{
List<T> list = Arrays.asList(a[i]);
map.put(a[i][0].getJobCategoryName(),list);
}
}
return map;
}
}
/**
* Returns a {@link Map} of job classes that have been
* loaded into the database
*
* @return a map of job classes that have been loaded into the database
*/
public Map<String,List<JobClass>> getJobClassList()
{
JobClass[][] categorizedClasses = common.getSlamdServer().getCategorizedJobClasses();
JobClassArrayHelper<JobClass> helper = new JobClassArrayHelper<JobClass>();
return helper.convert2dArrayToMap(categorizedClasses);
}
The JobClassArrayHelper converts the two-dimensional array of JobClass objects into a Map where the key is the job class category and the value is a java.util.List of JobClass objects. The Map is very easy to access in the JSP, let's take a look at that next.
The scheduleJob.jsp code
<%-- -*- html -*- --%>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%-- each action should generate its own title --%>
<%-- include the JSP for the sidebar navigation --%>
<%-- include the JSP for the page header --%>
<%-- if no job name was provided to the Action display the list
of jobs that have been loaded into the database --%>
Schedule a New Job
Choose the type of job to schedule from the following list:
<%-- set a variable to the job class param --%>
<%-- iterate over the keys in the map "jobClassList" --%>
<%-- the key in the map is the name of the job category --%>
Job Classes
<%-- The value in the map is the list of job classes.
Each element is of type com.slamd.jobs.JobClass. --%>
<%-- iterate of the list of job classes --%>
<%-- set the class name of the job class --%>
<%-- Construct the link that will cause a new job --
-- class to be scheduled. The link consists of the --
-- ScheduleJob.action, a title that might be
-- rendered as a tooltip, or spoken, and a job
-- class parameter with the parameter value set to --
-- the job class name. --%>
-
This is the entire scheduleJob.jsp file that handles the use case of listing all SLAMD jobs in the database. I'll pick it apart piece by piece.
I like emacs
The following snippet causes Emacs to turn on HTML mode (a major mode):
<%-- -*- html -*- --%>
Page content and taglibs
Set the DOCTYPE, content type, and make 's' the prefix for the Struts tags:
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
Basic page setup
In SLAMD3, each page will have its own id and set its own title. navigation.jsp and header.jsp are the same for each HTML page, so those are included in each page. Divs are used freely to set off sections of the pages like the navigation sidebar and the header from the "content":
<%-- each action should generate its own title --%>
<%-- include the JSP for the sidebar navigation --%>
<%-- include the JSP for the page header --%>
Categorized job class listing
Here's the interesting part. First, test whether the jobClassName is "noJob" (recall that this value comes from a static final in com.slamd.common.Constants) and if so, print a short message about creating a new job, and create a new div called "categorizedJobClassList". The "job_class" URL parameter string is set to a variable using the "set" Struts tag so it can be referenced later - in the hope that the code becomes easier to read. Next create an iterator with the "iterator" tag where the object to iterate over is "jobClassList". Note that Struts uses the bean convention and actually calls ScheduleJobAction.getJobClassList. Recall that the signature of getJobClassList is:
public Map> getJobClassList()
That is, a Map where the key is a String and the value is a List of JobClass objects.
<%-- if no job name was provided to the Action display the list
of jobs that have been loaded into the database --%>
Schedule a New Job
Choose the type of job to schedule from the following list:
<%-- set a variable to the job class param --%>
<%-- iterate over the keys in the map "jobClassList" --%>
iterate over the map
It is not strictly necessary to use the "set" tag as much as is used here, but I think it makes the code easier to read and understand. In this case, the key from the map is assigned to a variable "jobClassCategory", and the value to "listOfJobs".
<%-- the key in the map is the name of the job category --%>
Job Classes
<%-- The value in the map is the list of job classes.
Each element is of type com.slamd.jobs.JobClass. --%>
This part sets a variable "className" by calling the methods to retrieve the name of the class for each SLAMD job class, then constructs a link of the form "ScheduleJob.action?job_class=com.slamd.jobs.JobClass":
<%-- iterate of the list of job classes --%>
<%-- set the class name of the job class --%>
<%-- Construct the link that will cause a new job --
-- class to be scheduled. The link consists of the --
-- ScheduleJob.action, a title that might be
-- rendered as a tooltip, or spoken, and a job
-- class parameter with the parameter value set to --
-- the job class name. --%>
-
And that's it. The next use case - in a separate blog entry - is to present the job class form. This is all baby stuff to hard-core Struts developers, but I had to blog it so I would not forget how to do it, and hopefully others will get some value from this entry also.
Posted at
01:38PM Mar 12, 2009
by tgardner in slamd |
Comments[4]
SLAMD 2.0.0 available, roadmap begun
SLAMD 2.0.0 is now available as a WAR file. The WAR file can be dropped into any servlet container.
Progress has been made towards defining a roadmap for SLAMD. There are a number of client interface stability issues to address, we will call those "enhancements" and "bug fixes" or "software corrections". Also, some folks are coming forward with custom job classes, we will get those into the release as soon as possible.
One roadmap item is particularly interesting; moving SLAMD into an MVC model, perhaps using Struts as an application framework. Currently, HTML for the view is generated mostly by the AdminServlet. My plan is to separate this functionality, introduce JSPs, and so forth, to increase the stability and flexibility of SLAMD. This would be a major re-write of the interface (actions and interceptors instead of a single uber-servlet), and my plan is to create a new release of SLAMD to hold this effort: SLAMD3.
There are four mailing lists available: users@slamd.kenai.com, commits@slamd.kenai.com, dev@slamd.kenai.com, and issues@slamd.kenai.com. Subscribe here.
Posted at 04:12AM Feb 23, 2009 by tgardner in slamd |
SLAMD downloads and source code available.
|
Current Progress on SLAMD project site:
Links: |
Posted at 04:29AM Feb 21, 2009 by tgardner in slamd |
Monday Mar 30, 2009