<<

. 51
( 87 .)



>>

actual style sheet that is used for the portlet is dependent on the theme
selected. Using these styles will allow the portlets to look and feel integrated
well with other portlets and take on the selected theme™s behavior. Look for
the styles.css ¬les in directories starting from

<was-root>/installedApps/<node>/wps.ear/eps.war/themes/...

Next, let™s look at the actionPerformed method in the portlet class to
handle the requests to verify the datasource and to move to the next page
in con¬gure mode. Don™t add this code to your portlet just yet.
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




Portlet Development 305

/**
* Handle all Action requests
*/
public void actionPerformed(ActionEvent event)
throws PortletException {

PortletRequest request = event.getRequest();
PortletContext portletContext = getPortletConfig().getContext();
PortletLog log = portletContext.getLog();

// Get the action name
String actionName = event.getActionString();
if (log.isDebugEnabled())
log.debug("actionPerformed() processing action "+actionName);

if ("verify".equals(actionName)) {
verifyAction(request, portletContext);
}

if ("config_pg2".equals(actionName)) {
page2Action(request, portletContext);
}

}

/**
* Verify datasource action
*/
protected void verifyAction(PortletRequest request,
PortletContext portletContext)
throws PollException {

try {
// Get configuration form data bean from session
SessionData sessionData = SessionData.getSessionData(request);
ConfigureFormData formData = sessionData.getConfigureFormData();

// Update the persistence type and the datasource from request
// parameters, validate the input.
formData.updateDbParms(request);

// Check the datasource name and the database tables
// If an exception occurs put the exception message out
DbBroker dbBroker = new DbBroker(formData.getDatasource());
dbBroker.verifyTables();

// Success, put a message out
ResourceBundle bundle = ResourceBundle.getBundle("nls.polling",
request.getLocale());
String msg = bundle.getString("configure.verify_success");
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




306 Chapter 16

sessionData.setMessage(msg);

}
catch (PollException e) {
SessionData sessionData = SessionData.getSessionData(request);
sessionData.setMessage(e.getLocalizedMessage());
}

}

/**
* Prepare for configure mode page 2
*/
protected void page2Action(PortletRequest request,
PortletContext portletContext)
throws PollException {

// Get configuration form data bean from session
SessionData sessionData = SessionData.getSessionData(request);
ConfigureFormData formData = sessionData.getConfigureFormData();

// Update the persistence type and the datasource from request
// parameters, validate the input.
formData.updateDbParms(request);

// Get the list of current polls (by name) from the data store
// Get a broker instance using the form data parameters
Broker broker = Broker.getInstance(formData.getPersistType(),
formData.getDatasource());
List pollNames = broker.getPollNames();

// Put it in form data object
formData.setPollNames(pollNames);

}

You see in this example code that the actionPerformed method is
passed an ActionEvent object. From the ActionEvent you can get the
PortletRequest object and you can also get the name of the action event.
So, this single method becomes the dispatcher for all action event processing
for the portlet. In this example we show two action events, verify and
config_pg2, and the code in separate methods that needs to execute for
each of those events.
You can see that the actionPerformed method can become very clut-
tered with “if” statements while matching event name strings to invoke ap-
propriate application behavior. You can solve this problem easily by chang-
ing the action event names from arbitrary strings to class names and then
have the actionPerformed method in your portlet class get an instance
of that class and invoke its actionPerformed method. This allows you
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




Portlet Development 307


to ensure better separation of responsibility in our code. You will see in the
chapter titled Struts Portlet Framework that using the Struts framework to
develop our portlets solves this problem.
Your JSPs will have to be changed to specify fully quali¬ed class names
in their PortletURI tags. We also introduce an abstract Action class
as the superclass of our Action classes. The ActionClassManager is
used to return Action subclass instances given a class name. Then our
actionPerformed method is quite simple and looks like the following
(this can be added to the PollPortlet in the Studio project):

/**
* Handle all Action requests
*/
public void actionPerformed(ActionEvent event)
throws PortletException {

PortletRequest request = event.getRequest();
PortletContext portletContext = getPortletConfig().getContext();
PortletLog log = portletContext.getLog();

// Get the action handler class and dispatch
String actionClassName = event.getActionString();
Action action = ActionClassManager.getAction(actionClassName);
if (log.isDebugEnabled())
log.debug("Dispatching to action class "+actionClassName);

// Dispatch to that class event handler
action.actionPerformed(request, portletContext);
action.setView(request);
}


Now the code that was in the verifyAction method can be moved to
the actionPerformed method of the new class ConfigVerifyData-
sourceAction. Likewise, the code that was in the page2Action method
can be moved to the actionPerformed method of the new class Con-
figPg2Action.
The last structural change you will make will allow a similar separation
of concerns in our implementation for the render phase processing as you
just did for the action phase. You would have a similar problem with the
doConfigure method, as it would need to handle all render requests for
all con¬gure pages in our portlet. You would need to determine which page
in con¬gure mode you should render, and then create any necessary beans
and invoke the appropriate JSP. Again, you can segment this work out by
introducing the idea of View classes and use the Action event processing
to set the View class name to be dispatched to it during the render phase.
You see that in the setView method in the Action classes.
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




308 Chapter 16


Action Classes
The following is the ConfigVerifyDatasourceAction class:

/**
* Action - Handle the request to test the datasource
*/

public class ConfigVerifyDatasourceAction extends Action {
public void actionPerformed(PortletRequest request,
PortletContext portletContext) throws PollException {

try {

// Get configuration form data bean from session
SessionData sessionData = SessionData.getSessionData(request);
ConfigureFormData formData = sessionData.getConfigureFormData();

// Update the persistence type and the datasource from request
// parameters, validate the input.
formData.updateDbParms(request);

// Check the datasource name and the database tables
// If an exception occurs put the exception message out
DbBroker dbBroker = new DbBroker(formData.getDatasource());
dbBroker.verifyTables();

// Success, put a message out
ResourceBundle bundle = ResourceBundle.getBundle("nls.polling",
request.getLocale());
String msg = bundle.getString("configure.verify_success");
sessionData.setMessage(msg);

}
catch (PollException e) {
SessionData sessionData = SessionData.getSessionData(request);
sessionData.setMessage(e.getLocalizedMessage());
}
}

/**
* Set the next Portlet view. . . if this is a MODE change action
* (createReturnURI) then set the next view to null to allow the
* default view in the next mode
*/
public void setView(PortletRequest request)
throws PollException {
setView(request, CONFIG_STATE);
}
}
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




Portlet Development 309


The setView method in the abstract Action class simply sets the View
class name on the session object. During the render phase all you have to
do is retrieve the View class name from the session object and dispatch to
it. Realize that you can put the view class name on session using the portlet
mode as the session attribute name. That is, you can have a view attribute
on session, as well as con¬gure, edit, and help attributes, each specifying a
different View class name.
By implementing it this way, the user can leave con¬guration mode in
page 2, for example, and when the user returns to con¬gure mode he or
she will return to that page instead of starting over from the initial page.
Given this, you can dispatch not from the doView, doEdit, doConfigure
methods in our PollPortlet class but from the Service method. So the
Service method looks like the following:

/**
* Service method
*/
public void service(PortletRequest request, PortletResponse response)
throws PortletException, IOException {

PortletContext portletContext = getPortletConfig().getContext();
PortletLog log = portletContext.getLog();

<<

. 51
( 87 .)



>>