Thursday, February 19, 2009

Web Services,SOAP 1.2 and WSDL 1.1- Lecture at Harvard University(Computer Science)

One of the best Podcasts I have come across, on Web Services concepts...


Lecture 11: Web Services, SOAP 1.2, and WSDL 1.1

Harvard Extension School\'s Computer Science E-259: XML with J2EE




Double-click on the "blank" screen to start the video, I set "autoplay" option to false, just to make sure users who are not interested in this podcast don't get confused while browsing other content on this blog.

Note : If you fail to see this video, pls make sure you have "Quicktime" Player installed..

Wednesday, February 18, 2009

PERL Script for getting "Timestamps" -Files Creation Time

perl -e '@q=stat($ARGV[0]); print time-$q[9]' file1

ls -ltr


#!/usr/bin/perl

#^ PROGRAM DESCRIPTION
#^ -------------------
#^ This program prints the modification times and names of files.
#^ It uses the following format: inodetime.pl filename
#^ It will accept: inodetime.pl filename1 filename2 filename3
#^ inodetime.pl /tmp/file*
#^ The format of the output is: YYYYMMDDhhmmss filename
#^ example:
#^ $ inodetime.pl /tmp/t*
#^ 19961115105425 /tmp/test.sql
#^ 19970116113616 /tmp/tststat.pl
#^
#^###################################################################

# Get the (next) input from the command line
while ($curfile = $ARGV[0])
{
# Do following code block only if $curfile exists
if (-e $curfile)
{
# stat structure into variables
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat("$curfile");
# time structure into variables
local($sec,$min,$hr,$day,$mon,$yr,$wday,@dntcare) = localtime($mtime);
$yr = ($yr>=70) ? $yr+1900 : $yr+2000;
$yr="$yr";
$mon = (++$mon < 10) ? "0$mon" : "$mon";
$day = ($day < 10) ? "0$day" : "$day";
$hr = ($hr < 10) ? "0$hr" : "$hr";
$min = ($min < 10) ? "0$min" : "$min";
$sec = ($sec < 10) ? "0$sec" : "$sec";
# Rearrange in the YYYYMMDDhhmmss format and assign to $dte variable
$dte = join('',$yr,$mon,$day,$hr,$min,$sec);
# Print modification date and filename
print ("$dte $curfile\n");
}
# Shift to next position in command line
shift (@ARGV);
}



#! /usr/bin/ksh

typeset -Z2 d m
Jan=1 Feb=2 Mar=3 Apr=4 May=5 Jun=6 Jul=7 Aug=8 Sep=9 Oct=10 Nov=11 Dec=12
date "+%Y %m" | read year month

for i ; do
line=$(ls -dl $i)
line=${line##+([! ])+([ ])}
line=${line##+([! ])+([ ])}
line=${line##+([! ])+([ ])}
line=${line##+([! ])+([ ])}
line=${line##+([! ])+([ ])}
set -A stamp $line
d=${stamp[1]}
eval m=\$${stamp[0]}
y=${stamp[2]}
((${#y} != 4)) && ((y=year-(m>month)))
echo $y $m $d $i
done
exit 0

Adding Custom Events using JBoss JBPM - JPDL

Adding Custom Events



Goal: Provide a mechanism to suspend a task for a period of time, and automatically resume the task after the time period is up.

Solution: Add custom Events for task suspend and task resume, override the suspend and resume methods in a custom task instance to fire the suspend and resume events.

1) Optional - Add two new EVENTTYPEs for suspend and resume to the org.jbpm.graph.def.Event class. (not necessary however, just a convenience)

public static final String EVENTTYPE_TASK_SUSPEND = "task-suspend";
public static final String EVENTTYPE_TASK_RESUME = "task-resume";

2) Optional - Add these to the supported EventTypes in the org.jbpm.graph.def.Task class. (not necessary since jBPM determines event-types dynamically).

static final String[] supportedEventTypes = new String[]{
Event.EVENTTYPE_TASK_CREATE,
Event.EVENTTYPE_TASK_ASSIGN,
Event.EVENTTYPE_TASK_START,
Event.EVENTTYPE_TASK_END,
Event.EVENTTYPE_TASK_SUSPEND,
Event.EVENTTYPE_TASK_RESUME

2) Subclass .jbpm.graph.exe.TaskInstance

Override Suspend and Resume

public void suspend(String date) {
super.suspend();
if ( (task!=null)
&& (token!=null)
) {
ExecutionContext executionContext = new ExecutionContext(token);
// the TASK_SUSPEND event is fired
executionContext.setTaskInstance(this);
executionContext.setTask(task);
executionContext.getTaskInstance().setVariable("suspendUntilDate", date);
task.fireEvent(Event.EVENTTYPE_TASK_SUSPEND, executionContext);
}
}

public void resume() {
super.resume();
if ( (task!=null)
&& (token!=null)
) {
ExecutionContext executionContext = new ExecutionContext(token);
// the TASK_RESUME event is fired
executionContext.setTaskInstance(this);
executionContext.setTask(task);
task.fireEvent(Event.EVENTTYPE_TASK_RESUME, executionContext);
}
}

3) Configure the timer on the task

<process-definition
xmlns="urn:jbpm.org:jpdl-3.1"
name="simple">
<action name="resume" class="com.sample.action.ResumeActionHander" />

<start-state name="start">
<transition name="" to="Create Order"></transition>
</start-state>
<end-state name="end"></end-state>
<task-node name="Approve Order" create-tasks="true">
<task name="approve" description="Review order">
<assignment class="com.sample.assignment.SomeAssignmentHandler"
</assignment>
<event type='task-suspend'>
<action name="Suspend Timer" class="com.sample.action.CreateTimerActionHandler">
<action>resume</action>
</action>
</event>
<event type="task-resume">
<action name="SendMessage" class="com.sample.action.MessageActionHandler">
<message>resumed the task instance</message>
</action>
</event>
<controller class="com.sample.taskinstance.CustomTaskControllerHandler"></controller>
</task>
<transition name="" to="end"></transition>
</task-node>
...
</process-definition>

4) Implement CreateTimerActionHandler

public class CreateTimerActionHandler implements ActionHandler {

private String action;

private static final long serialVersionUID = 1L;

/** {@inheritDoc} */
public void execute(ExecutionContext executionContext) throws Exception {
Timer timer = new Timer(executionContext.getToken());
timer.setName(executionContext.getAction().getName());

TaskInstance taskInstance = executionContext.getTaskInstance();
String dueDate = (String)taskInstance.getVariable("suspendUntilDate");

// parse the due date
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.SHORT);
Date date = format.parse(dueDate);
timer.setDueDate(date);

// retrieve a named action from the process definition
Action action = executionContext.getProcessDefinition().getAction(
this.action);
timer.setAction(action);
// set the TaskInstance so the resume action knows what taskInstance to resume
timer.setTaskInstance(taskInstance);

SchedulerService schedulerService = (SchedulerService) Services
.getCurrentService(Services.SERVICENAME_SCHEDULER);
schedulerService.createTimer(timer);
}
}

5) Implement ResumeActionHandler

public class Resume implements ActionHandler {
public class ResumeActionHandler implements ActionHandler {

private static final long serialVersionUID = 1L;

public void execute(ExecutionContext executionContext) throws Exception {
System.out.println("resuming taskInstance");

TaskInstance taskInstance = executionContext.getTaskInstance();
System.out.println("TaskInstance is " + taskInstance);

CustomTaskInstance cti = (CustomTaskInstance) executionContext.getJbpmContext().getSession().load(CustomTaskInstance.class, new Long(taskInstance.getId()));
cti.resume();
}
}

Creating "Timer" tasks in JBoss JBPM using JPDL

NOTE: This example has not been updated to work with jBPM versions 3.2 or greater.

Use-Case
Suppose you receive an order on 2006/10/05 and some related task is created on 10/7; the task needs to be done within 5 days of recieving the order. How do we do that?
jBPM's definition language, JPDL, does not provide a packaged mechanism for dynamically setting Due Dates on Timers and Tasks based on arbitrary data. However, it is not too difficult to work up a solution that brings us the flexibility we need. Here is an example that takes advantage of an ActionHandler? to set these due dates dynamically based on a process instance variable:

<?xml version="1.0" encoding="UTF-8"?>
<process-definition name="Due date Test">
<start-state name='START' >
<transition name='done' to='NODE1'/>
</start-state>

<task-node name='NODE1'>
<task name='task1'/>
<event type='node-enter' >
<create-timer name='myTimeout' duedate='2000 days' >
<script>System.out.println("I reset my timer!");</script>
</create-timer>
<!-- Dynamically set due date of the timer created in the line above.
(This ActionHandler can also be used to dynamically set a Task's due date
by substituting the <timerName> tag with a <taskName> tag) -->
<action name='setThisTimer' class='com.???.UpdateDueDateAH'>
<timerName>myTimeout</timerName>
<!-- Process instance variable containing a java.util.Date. This value will
be used as a base value for calculating the Timer's new due date. If not
provided, the current time will be used. -->
<baseTimeVar>testDate</baseTimeVar>
<!-- The 'baseTimeVar' Date can be modified by optionally adding a period of
time. The value is a valid jBPM Duration styled string -->
<addDuration>2 minutes</addDuration>
</action>
</event>
<event type='node-leave' >
<!-- To mimic the 'node context' of the short hand timer syntax <timer>, we
would need to ensure that our timer is cancelled on node exit. -->
<cancel-timer name='timeout' />
</event>
<event type='task-create'>
<!-- Use UpdateDueDateAH here to dynamically set a task's due date -->
<action name='setDueDate' class='com.???.UpdateDueDateAH'>
<taskName>task1</taskName>
<baseTimeVar>testDate</baseTimeVar>
<addDuration>5 minutes</addDuration>
</action>
</event>
<transition name='done' to='NODE2'/>
<transition name='_sys_redoNode' to='NODE1'/>
</task-node>

<state name='NODE2'>
<!-- Timers with this syntax are created on node-enter and cancelled on node-leave.
If timer creation is needed from within an event element or the timer should continue
after the node has exited, then use <create-timer> instead -->
<timer name='thisNodeOnlyTimeout' duedate='5 minutes' transition='done' />
<transition name='done' to='END'/>
</state>

<end-state name="END" />
</process-definition>
...and here is the UpdateDueDateAH? class:
/*
* UpdateDueDateAH.java
*
*
*/

package com.???;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.*;

import org.jbpm.calendar.BusinessCalendar;
import org.jbpm.calendar.Duration;

import org.jbpm.svc.Services;
import org.jbpm.scheduler.SchedulerService;
import org.jbpm.db.SchedulerSession;
import org.jbpm.scheduler.exe.Timer;

import java.io.*;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class UpdateDueDateAH implements ActionHandler{

//-- variables set by process def action parameter elements --
private String baseTimeVar = null;
private String addDuration = null; //a jbpm Duration styled string
private String timerName = null; //either this OR taskName should be set
private String taskName = null; //either this OR timerName should be set

private ExecutionContext ec = null;
public Log log = LogFactory.getLog(this.getClass());

public UpdateDueDateAH() {
}

/*Execute the action handler*/
public void execute(ExecutionContext executionContext){
ec = executionContext;
try{
Token token = ec.getToken();

Date newDueDate = null;
if(timerName != null) {
SchedulerSession schedulerSession = ec.getJbpmContext().getSchedulerSession();
//apparently throws an exception if no timer is found...
List timers = schedulerSession.findTimersByName(timerName, token);
for(Object o : timers) {
Timer timer = (Timer)o;
try{
newDueDate = this.calculateDueDate();
timer.setDueDate(newDueDate);
}catch(Exception e) {
throw new Exception("Timer '" + timer.getName() + "' due date was not updated to " +
newDueDate + "': " + e);
}
schedulerSession.saveTimer(timer);
log.info("Timer '" + timer.getName() + "' due date updated to " + timer.getDueDate());
}
}else if(taskName != null) {
TaskMgmtInstance tmi = ec.getTaskMgmtInstance();
for(Object o : tmi.getTaskInstances()) {
TaskInstance task = (TaskInstance)o;
//if wildcard is specified, update all tasks...
if(taskName.equals("*")) {
try{
newDueDate = this.calculateDueDate();
task.setDueDate(newDueDate);
}catch(Exception e) {
throw new Exception("Task '" + task.getName() + "' due date was not updated to " +
newDueDate + "': " + e);
}
log.info("Task '" + task.getName() + "' due date updated to " + task.getDueDate());
}else{
if(taskName.equals(task.getName())) {
try{
newDueDate = this.calculateDueDate();
task.setDueDate(newDueDate);
}catch(Exception e) {
throw new Exception("Task '" + task.getName() + "' due date was not updated to '" +
newDueDate + "': " + e);
}
log.info("Task '" + task.getName() + "' due date updated to "+task.getDueDate());
}
}
}
}

}catch(java.lang.Exception e){
log.error(e.getMessage(), e);
}
}

private Date calculateDueDate() throws Exception {
Date dueDate = null;

Calendar cal = Calendar.getInstance();
//if a baseTime is specified, we'll use that; otherwise, we'll just use the current time
if(baseTimeVar != null && baseTimeVar.length() > 0) {
Object baseTime = ec.getContextInstance().getVariable(baseTimeVar);
if(baseTime != null) {
if(baseTime instanceof String) {
throw new Exception("Could not calculate Due Date: the variable '" + baseTimeVar + "' should be a type of java.util.Date.");
}else if(baseTime instanceof Date) {
cal.setTime((Date)baseTime);
}else{
throw new Exception("Could not calculate Due Date: baseTimeVar '" + baseTimeVar +
"' was specified but no valid date/time data was found.");
}
}else{
throw new Exception("Could not calculate Due Date: baseTimeVar was specified but no data was found.");
}
}

if(addDuration != null) {
BusinessCalendar businessCalendar = new BusinessCalendar();
Duration duration = new Duration(addDuration);
dueDate = businessCalendar.add( cal.getTime(), duration );
}

return dueDate;
}

public void setTimerName(String timerName) {
if(timerName != null && timerName.trim().length() > 0) this.timerName = timerName;
}

public void setTaskName(String taskName) {
if(taskName != null && taskName.trim().length() > 0) this.taskName = taskName;
}

public void setBaseTimeVar(String baseTimeVar) {
this.baseTimeVar = baseTimeVar;
}

/*
* Takes a jbpm Duration styled string
*/
public void setAddDuration(String addDuration) {
this.addDuration = addDuration;
}
}

Softwares used : JBoss JBPM JPDL 3.2.2, XML

Deploying JBoss JBPM Web Console(3.2.2) on Weblogic 9.2

Steps to deploy the jbpm-console on Weblogic 9.1 and Oracle 9i


Note: I didnt try this effort using latest JBoss JBPM Version,if you run into issues with new version,let me know..

1. Download the jbpm- jPDL Suite (jbpm-jpdl-3.2.1.zip) or the latest stable version jbpm-jpdl-3.2.2 from http://sourceforge.net/project/showfiles.php?group_id=70542&package_id=145174

2. Extract to C:\

3. Go to deploy folder at C:\jbpm-jpdl-3.2.2\deploy

4. Create a new Folder jbpm-console

5. Create a directory structure as,
C:\jbpm-jpdl-3.2.2\deploy\jbpm-console
\build
\dist
\src
\WebContent
\build.xml

6. The contents of build.xml are :

<project basedir="." default="create.war">
<property name="dist" value="dist" />

<target name="create.war">
<war destfile="dist/jbpm-console.war" webxml="WebContent/WEB-INF/web.xml" basedir="WebContent">
</war>
</target>
</project>

7. The contents of WebContent folder are, the directory structure is,
WebContent
\images
\META-INF
\sa
\ua
\WEB-INF
\index.jsp
Just copy the webapp contents from c:\jbpm-jpdl-3.2.2\deploy\webapp into WebContent folder

8.The contents of index.jsp file are :

<%
final String queryString = request.getQueryString();
final String contextRoot = request.getContextPath();
final String target = contextRoot + "/sa/processes.jsf";
if (queryString != null && queryString.length() > 0) {
response.sendRedirect(target + "?" + queryString);
} else {
response.sendRedirect(target);
}
%>


9. Go to WebContent folder and remove jboss-web.xml

10.Go to WebContent\WEB-INF\classes folder and edit hibernate.cfg.xml file

Add these lines ,

<property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>

<!-- JDBC connection properties (begin) -->

<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@HOSTNAME:1521:SID</property>
<property name="hibernate.connection.username">USER</property>
<property name="hibernate.connection.password">PASS</property>

<!-- JDBC connection properties (end) -->

<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>

<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

Comment these lines in hibernate.cfg.xml

<!-- DataSource properties (begin) === -->
<!-- <property name="hibernate.connection.datasource">java:/JbpmDS</property>
==== DataSource properties (end) -->

Assumption:jbpm tables already created on the Oracle 9i application schema.

<!-- identity mappings (begin) -->
<!-- <mapping resource="org/jbpm/identity/User.hbm.xml"/>
<mapping resource="org/jbpm/identity/Group.hbm.xml"/>
<mapping resource="org/jbpm/identity/Membership.hbm.xml"/>
identity mappings (end) -->

<!-- logging properties (begin) ===
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.use_sql_comments">true</property>
==== logging properties (end) -->

11. Copy the following jars from C:\jbpm-jpdl-3.2.1\server\server\jbpm\lib
to C:\jbpm-jpdl-3.2.1\deploy\jbpm-console\WebContent \WEB-INF\lib
commons-beanutils.jar
dom4j.jar
antlr-2.7.6.jar
ojdbc14.jar
hibernate3.jar
jboss-backport-concurrent.jar
commons-digester.jar
cglib.jar
jbpm-jpdl.jar
bsh.jar
jbossretro-rt.jar
commons-logging.jar
asm.jar
stax-api-1.0.jar
wstx-lgpl-2.0.6.jar
commons-collections.jarjboss-retro-1.1.0-rt.jar
cglib.jar
jbpm-jpdl.jar
bsh.jar
jbossretro-rt.jar
commons-logging.jar
asm.jar
stax-api-1.0.jar
wstx-lgpl-2.0.6.jar
commons-collections.jar

12. Edit the access.properties file in C:\jbpm-jpdl-3.2.2\deploy\jbpm-console\WebContent\WEB-INF and add the user roles the application needs, like

role.identities.user=manager,admin,user
role.identities.user.add=manager,admin,user
role.identities.user.delete=manager,admin,user
role.identities.user.modify=manager,admin,user

role.identities.group=manager,admin,user
role.identities.group.add=manager,admin,user
role.identities.group.delete=manager,admin,user
role.identities.group.modify=manager,admin,user

# Process definition operations
role.process.deploy=manager,admin,user
role.process.delete=manager,admin,user
role.process.start=manager,admin,user

# Process instance and token operations
role.execution.suspend=manager,admin,user
role.execution.edit=manager,admin,user
role.execution.delete=manager,admin,user
role.execution.end=manager,admin,user

# Task management operations
role.tasks=manager,admin,user
role.task.assign=manager,admin,user
role.task.assign.any=manager,admin,user
role.task.modify=manager,admin,user

# Job management operations
role.jobs=manager,admin,user
role.jobs.delete=manager,admin,user

13. Add weblogic.xml in C:\jbpm-jpdl-3.2.2\deploy\jbpm-console\WebContent\WEB-INF
The contents are :

<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd
http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<jsp-descriptor>
<debug>true</debug>
</jsp-descriptor>
<context-root>jbpm-console</context-root>
</weblogic-web-app>

14. Edit the web.xml file C:\jbpm-jpdl-3.2.1\deploy\jbpm-console\WebContent\WEB-INF
And comment these lines

<!-- <security-constraint>
<web-resource-collection>
<web-resource-name>Secure Area</web-resource-name>
<url-pattern>/sa/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>-->

<!-- Login configuration option #1 - use the login page ==>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/ua/login.jsf</form-login-page>
<form-error-page>/ua/login.jsf?error=true</form-error-page>
</form-login-config>
</login-config>
<!== End Login configuration option #1 -->

<!-- Login configuration option #2 - use basic auth ==>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>jBPM Administration Console</realm-name>
</login-config>
<!== End Login configuration option #2 -->

And ,
<!-- This section is so that the web console can deploy in the jbpm-enterprise.ear module -->

<!-- <ejb-local-ref>
<ejb-ref-name>ejb/LocalTimerServiceBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>org.jbpm.scheduler.ejbtimer.LocalTimerServiceHome</local-home>
<local>org.jbpm.scheduler.ejbtimer.LocalTimerService</local>
<ejb-link>TimerServiceBean</ejb-link>
</ejb-local-ref> -->

15. After making all these changes, run “ant build.xml” from C:\jbpm-jpdl-3.2.2\deploy\jbpm-console at command prompt and then “ ant create.war” to create the jbpm-console.war file in “C:\jbpm-jpdl-3.2.2\deploy\jbpm-console\dist”

16. Copy this war file in C:\bea91\user_projects\domains\PRJ_DOMAIN\autodeploy and start your application server to deploy jbpm console on weblogic

17. Go to http://localhost:7001/jbpm-console

18. Softwares Needed :
Ant 1.6.5/Ant1.7 , weblogic 9.0/9.1/9.2 , jbpm-jpdl-3.2.2 suite

19.While deploying this war file on weblogic if you get any exceptions listed below, follow the solutions given below

a) javax.enterprise.deploy.spi.exceptions.InvalidModuleException: [J2EE Deployment SPI:260105]Failed to create DDBeanRoot for application, 'C:\jbpm-jpdl-3.2.1\deploy\jbpmgui.war'
use 2.3 dtd instead of 2.4 xsd

<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd
http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

b) error 503 service unavailable
Set the following Environment variables:
i) JAVA_HOME = c:\bea\jdk142_08\bin;C:\bea\jrockit81sp5_142_08\bin;
ii) ANT_HOME = c:\ant\bin
iii) CLASSPATH = c:\bea\weblogic91\server\lib;C:\bea\weblogic91\server\lib\Weblogic.jar;
(You might need to set some of these CLASSPATHS after building the WAR files)


Any questions, please leave comments and suggestions are more than welcome...

Introduction to "Wicket" Web Framework

Wicket, is an open source, lightweight, component-based Java web framework
that brings the Java Swing event-based programming model to web development

Wicket allows you to easily customize this default behavior though. All user pages typically extend Wicket’s WebPage—a subclass of Wicket’s Page class. There needs to be a one-to-one correspondence between the HTML elements with a wicket:id attribute and the Page components

In Wicket,a model (an object implementing the IModel interface) acts as the source of data for a component..

Wicket could also be classified as an event-driven framework. Wicket HTML components
register themselves as listeners (defined through several Wicket listener interfaces) for requests originating from the client browser. For example, Wicket’s Form component registers itself as an IFormSubmitListener, while a DropDownChoice implements the IOnChangeListener interface. When a client activity results in some kind of request on a component, Wicket calls the corresponding listener method. For example, on an HTML page submit, a Form component’s onSubmit() method gets called, while a change in a drop-down selection results in a call to DropDownChoice.onSelectionChanged

With proper mark-up/logic separation, a POJO data model, and a refreshing lack of XML, Wicket makes developing web-apps in Java simple and enjoyable again. Swap the boilerplate, complex debugging and brittle code for powerful, reusable components written with plain Java and HTML.

The component’s id value must match the wicket:id attribute of the
template’s corresponding HTML component

During the page render phase, Wicket does the following:
1. It kicks off the page rendering process by calling the Page.render() method.
2. The Page locates the corresponding markup template and begins iterating over the
HTML tags, converting them into an internal Java representation in the process.
3. If a tag without wicket:id is found, it is rendered as is.
4. If a tag with wicket:id is found, the corresponding Wicket component in the Page is located, and the rendering is delegated to the component.
5. The Page instance is then stored in an internal store called PageMap. Wicket maintains one PageMap per user session.

In Wicket, the component hierarchy is specified explicitly through Java code—which allows you to modularize code and reuse components via all the standard abstraction features of a modern object-oriented language. This is quite different from other frameworks like Tapestry, wherein the page components are typically specified in an XML page specification file listing the components used in the page

WicketServlet expects to be supplied with an IWebApplicationFactory implementation in
order to delegate the responsibility of creating the WebApplication class. A factory implementation could be specified as a servlet initialization parameter in web.xml against the key application➥FactoryClassName. In the absence of such an entry, WicketServlet uses ContextParamWeb➥ApplicationFactory by default. As the name suggests, this class looks up a servlet context parameter to determine the WebApplication class name. The expected web.xml param-name in this case is
applicationClassName. ContextParamWebApplicationFactory works perfectly for majority of the cases Register the CompoundPropertyModel instance with the parent component,
* Form in this case, for the children to inherit from. So all the * remaining components will then use the UserProfile instance * as its model, using OGNL like 'setters' and 'getters'

Wicket’s CompoundPropertyModel allows you to use each component’s ID as a property-path expression to the parent component’s model

Wicket looks for the presence of a system property called wicket.configuration first. If it doesn’t find one, it looks for the value corresponding to a servlet initialization parameter named configuration. In the absence of the preceding settings, it looks for an identical servlet context parameter setting. If none of the
preceding listed lookups succeed, Wicket configures the application in development mode by default. Note that the value for configuration has to be either development or deployment identified by fields wicket.Application.DEVELOPMENT and wicket.Application.DEPLOYMENT, respectively

You must be curious about the parameter bookmarkablePage in the URL. Actually, there is nothing special that makes the page bookmarkable. Any page is considered bookmarkable if it has a public default constructor and/ or a public constructor with a PageParameters argument. A bookmarkable page URL can be cached by the browser and can be used to access the page at a later point in time, while a nonbookmarkable
page cannot be accessed this way. A non-bookmarkable page URL makes sense only in the
context it was generated. If the page wants to be bookmarkable and accept parameters off the URL, it needs to implement the Page(PageParameters params) constructor

After the page is rendered, it is put into a PageMap. The PageMap instance lives in session and keeps the last n pages ( this number is configurable through Wicket’s ApplicationSettings object). When a form is submitted, the page is brought back from PageMap and the form handler is executed on it. The PageMap uses a Least Recently Used (LRU) algorithm by default to evict pages—to reduce space taken up in session.
You can configure Wicket with your own implementation of the eviction strategy. Wicket specifies the strategy through the interface wicket.session.pagemap.IPageMapEvictionStrategy. You can configure
your implementation by invoking getSessionSettings().setPageMapEvictionStrategy
(yourPageMapEvicationStrategyInstance) in the WebApplication.init() method

Component.setResponsePage method can be used to direct the user to a different page after page submit feedback component using Wicket’s built-in ListView

Wicket has a FeedbackPanel component that can display all types of messages associated with components nested within a page

Note that Wicket does call validate() on the subsequent components,
even if a component featured ahead in the page hierarchy has failed validation, accumulating the error messages on the way.

Validation in Wicket is specified through the IValidator interface. Since you can attach any number of IValidator interface implementations to a Wicket component through the component’s overloaded add() method, Wicket developers have made sure that they can be chained as well Validators are thread-safe. It is OK to link the same validator instance with multiple components

It acts as a translation layer between HTTP request parameters
and your model class, and the way it does this is through converters
Wicket accesses the converters through a factory class and makes it centrally available through Wicket’s ApplicationSettings class

All converters are supposed to implement the IConverter interface. It has a single
method: public Object convert(Object value, Class c)
All components allow you to specify the custom converter through the
getConverter() method

FeedbackMessages acts as a container for messages logged at any level, namely debug, info, error, warn. You can access messages specified at a particular log level in the form of a list (java.util.List) by supplying a filter of the type IFeedbackMessageFilter to FeedbackMessages

Using BPM for Software Delivery-The Process

Using BPM for Software Delivery

Traditional Approach:
1. Software projects go through requirements analysis. This phase involves talking to business and get individual requirements in document fashion and then are converted into software design and implementation decisions.
2. These requirements together form complete picture.
3. In that sense it is bottom-up design approach. Which leaves a lot to interpretation when it comes to how business and IT “see” the complete picture of organizational flow of information.

BPM Approach:
1. Main way it differs from traditional approach is that, it is top-down approach. Meaning it should start with Business Analysts and/or Users creating block diagrams to describe their overall flow of information in complete manner.
2. These blocks can be as abstract or detailed as Business can provide or wants them to be.
3. Each of these blocks interact with others via various synchronous/asynchronous mechanisms there by enabling Service Oriented Architecture (SOA) in the design and foundational infrastrure of all business requirements.
4. This also will automatically make sure all the sides involved “see” EXACT same “big picture” and can agree on the same.
5. Corollary effect of that is to allow all levels to drill down , see interdependencies, and make whole organization flexible, and more responsive to changes/updates.
6. Increased ROI, Risk-mitigation, reduced cost and other benefits follow the above.
***** BPM tool is ideal for flows of information that can be depicted as individual tasks that are controlled by some business logic or rules and can in general be described as a “process”
Most, if not all business process can be described in such a manner,
***

Implementation methodology:
To achieve BPM enabled software delivery following steps should be taken.
1. Business users/Analysts will provide Block diagram describing the process in terms of individual steps, decisions and flows.
This is very much like the “flow-charts” that all are familier with. Any IDE based tool of BPM (Jboss JBPM Engine) provides an easy to use and quick to adapt designer (Eclipse based Graphical Process Designer (GPD)) that can be used for this purpose.
This tool will create a simple text (xml formatted) file. Please see attached diagram below for example of such an image.

2.These blocks are then filled with details of functionality that is represented by that block.This normally means business analyst and business users doing requirements analysis and create a simple document that will give following information.
a. Globally applicable rules for process flows.
a. – These might include details such as business units responsible and allowed to see this process.
b. What are global variables if any are there any rules or validation that apply when this process fits in bigger flow as a sub-process maybe. (for e.g. Create Employee Payroll process might be a sub-process to Hire New Employee Process and can only be run if new employee SSN is validated against legal dept’s validate SSN service”)
c. Global tasks needed which can be organization wide rules or task. (for. e.g. upon completion of each order above email may be sent to manager)
b. Each individual block should then be given detailed description with following pieces
a. What is the functionality? Describe actual task
b. Timers and notification info – Due date, (if any) escalation actions (might be emails to supervisors, automated DB updates) , Rules for sending emails on task start, completion, expiring of task due dates etc.
c. Assignment and management rules – What business roles should be able to start/complete/stop task. Is task automatically sent to some user or is there specific set of rule for doing so.
d. User Interface details – Does task have any specific screen that should be associated while performing that task.
e. Auditing information – What are the business Process measurement matrices that are needed. (for e.g. Number of Orders processed in a day? Total Orders not completed in time, How many employees have more than 10 tasks in their to-do list etc)
f. If there is existing application/code that already does a particular functionality depicted by a block it should be noted and it will be RE-USED in almost all cases.
g. After all the above are given, any other specific rules, details of tasks, out of ordinary requests etc should be noted in a separate section under each block details.

3. Block diagram and subsequent info then is sent to IT for analysis and IT will create design and solution.
a. After previous steps and input from them, IT basically has all the info needed. At this point IT will likely look for re-use, application integration of existing coded functionality, and custom coding of new or updated functionality. But even if individual step is missed or has bugs.. the “BIG PICTURE” will be exactly what business has in mind.
b. IT does not have to write code to follow business flow, BPM tools will automatically do that based on outcome of individual business steps.
c. Business performance matrices become automatically available. – For this BPM tool will integrate with outside monitoring tools as needed,

Possible reasons for Web Application Memory Leaks-And Solutions

1) Check the version of CGLIB Jar Version deployed in container

And possible known classes in CGLIB which cause memory leak are present in Package - net.sf.cglib.proxy and these are the Classes with bugs
a) LazyLoader b) InvocationHandler c) Enhancer

The fix has been applied in CGLIB 2.2 JAR

2) If your application uses Spring Framework for Dependency Injection and JavaBeans Introspection,make sure the WebApp Domain, deployment descriptor "web.xml" has references to different Spring Listener classes like org.springframework.web.util.Log4jConfigListener & org.springframework.web.context.ContextLoaderListener

Spring offers another listener : org.springframework.web.util.IntrospectorCleanupListener

This is the Listener that flushes the JavaBeans Introspector cache on web app shutdown. Register this listener in "web.xml" to guarantee proper release of the web app class loader and the classes that it holds.

If the JavaBeans Introspector has been used to analyze application classes, the Introspector cache will hold a hard reference to those classes. Consequently, those classes and the web app class loader will not be garbage collected on web app shutdown!

Unfortunately, the only way to clean up the Introspector is to flush the entire cache, as there is no way to specifically determine the application's classes referenced there. This will remove cached introspection results for all other applications in the server too.

Note that this listener is not necessary when using Spring's beans infrastructure, as Spring's own introspection results cache will immediately flush an analyzed class from the JavaBeans Introspector cache.

Application classes hardly ever need to use the JavaBeans Introspector directly, so are normally not the cause of Introspector resource leaks. Rather, many libraries and frameworks do not clean up the Introspector..

Note that a single such Introspector leak will cause the entire web app class loader to not get garbage collected! This has the consequence that you will see all the application's static class resources (like singletons) around after web app shutdown, which is not the fault of those classes!

Possible Solution : Add this code in web.xml and place it before any other Spring Listeners

<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>

3) Problem with DOM4J JAR

There's a problem with the use of ThreadLocals for caching, it's never cleaned up. If the ClassLoader is thrown away (e.g. if a webapp is reloaded), then the ThreadLocal stuff hold until the Thread dies, which might take a while in a Servlet container where the Threads are pooled. In such situation, DOM4J would prevent the webapp's ClassLoader to be garbage collected, which would creates a a memory leak and eventually an OOM if the webapp is reloaded too many times.

Workaround : if possible,avoid using ThreadLocal class(Programmatically it can be done)

4) Get the latest version of JDOM JAR...the latest version 1.1 has fix for known memory leak issues being caused by org.jdom.input.SAXHandler class in older versions

5) Last but not the least, make sure you have Java Profilers like Eclipse Profiler Plugin(this is the best as far as Iam concerned), JProbe ,VisualGC or JSTAT running against web application server...

Feel free to add any more known bugs which cause memory leaks.....!!