Introduzione
Scopo di questo articolo è mostrare il porting
di una portlet con funzionalità CRUD illustrata
nell' articolo precedente, su Jetspeed 2, adottando
una architettura maggiormente Spring/Ioc-oriented.
Nell' articolo non si terrà conto delle autorizzazioni
dell' utente e dei messaggi di errore lato client.
Nel precedente articolo, è stato mostrato come
la portlet era dotata di un metodo per ciascuna delle
operazioni, e poneva nel contesto di Velocity gli oggetti
per rappresentare i risultati ottenuti, potevamo usare
un solo template vm con delle condizioni di visualizzazione
in base alle operazioni richieste.
Nel caso di Jetspeed2 invece abbiamo due soli metodi
di accesso, il processAction e il doView (oltre al doHelp
e al doEdit). Perciò useremo il metodo doView
per la visualizzazione "normale" in cui operiamo
sulle altre portlet, e il processAction per inoltrare
tutti i metodi che invocavamo in Jetspeed 1 direttamente
alla portlet.
Figura 1 - RicettarioPortlet
(clicca sull'immagine per ingrandire)
Nell' articolo precedente abbiamo usato Spring solamente
per lo strato di accesso ai dati, qui lo useremo in
maniera ancora più estesa, infatti, ad esclusione
della sola classe RicettarioPortlet, tutte le altre
sono costruite per utilizzare l' Inversion of Control
fornito da Spring.
Lo strato di accesso ai dati e l'ascoltatore (Servlet
Listener) continueranno ad essere quelli dell' articolo
precedente,
cambia la modalità di recupero, in quanto non
avviene più nella portlet, ma nel controller,
basandosi sul file di configurazione dei beans, perciò
il DAO verrà iniettato nel Controller e non più
recuperato dall' ApplicationContext con il lookup.
Architettura
Prendendo spunto dalla architettura MVC di Spring :
Figura 2 - Spring MVC
strutturiamo
la nostra portlet in questo modo:
Figura 3 - RicettarioPortlet
(clicca sull'immagine per ingrandire)
Alla portlet arrivano delle RenderRequest o delle ActionRequest,
e viene delegato alla classe che implementa l' Interfaccia
IRicettarioController il lavoro vero e proprio. Quindi
la nostra portlet fa la parte della Dispatcher servlet,
agendo da front controller.
Figura 4 - IRicettarioController
La classe RicettarioController contiene nel metodo processActionRequest,
la logica di business che
smista le operazioni richieste, a tutti gli effetti
lavora come un Controller di Spring.
Il Contoller in ognuno dei suoi metodi assegna il modello
e la view (Spring ha un oggetto ModelAndView che li
contiene) che viene visualizzato nella jsp prescelta.
Il corrispondente della view di SpringMVC, è
la jsp che viene inclusa nella nostra dispatcher.jsp.
L'HandlerMapping e il ViewResolver nella nostra portlet
non sono presenti, in quanto non abbiamo bisogno di
gestire url di richiesta diversi ne tantomeno diverse
tecnologie di visualizzazione in quanto usiamo le sole
jsp.
Implementazione
Vediamo per prima cosa la portlet:
/*
* Copyright 2000-2001,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the
"License");
* you may not use this file except in compliance with
the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in
writing, software
* distributed under the License is distributed on an
"AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
* See the License for the specific language governing
permissions and
* limitations under the License.
*/
/**
*@author Massimiliano Dessì
*@created 13 marzo 2005
*/
package org.casamia.cucina.ricettario.portlet;
import
org.casamia.cucina.ricettario.services.IServizio;
import org.casamia.cucina.ricettario.util.Costanti;
import
javax.portlet.*;
import java.io.IOException;
public
class RicettarioPortlet extends GenericPortlet {
/**
* Description of the Method
*/
public void init() {
IServizio srv = (IServizio) getPortletContext().getAttribute(
Costanti.SERVIZIO);
_rc = (IRicettarioController) srv.getApplicationContext().getBean(Costanti.NOME_CONTROLLER);
}
/**
* Description of the Method
*
*@param request Description of the Parameter
*@param actionResponse Description of the Parameter
*@exception PortletException Description of the Exception
*@exception IOException Description of the Exception
*/
public void processAction(ActionRequest request,
ActionResponse actionResponse) throws PortletException,
IOException {
_rc.processActionRequest(request, actionResponse);
}
/**
* Description of the Method
*
*@param request Description of the Parameter
*@param response Description of the Parameter
*@exception PortletException Description of the Exception
*@exception IOException Description of the Exception
*/
public void doView(RenderRequest request, RenderResponse
response)
throws PortletException, IOException {
_rc.processRenderRequest(request, response, getPortletContext());
}
public void destroy() {
_rc.cleanUp();
}
private IRicettarioController _rc;
}
Come si vede, nell' init recuperiamo attraverso il Servizio
e l' ApplicationContext il RicettarioController, questo
è l'unico lookup che viene fatto, e una sola
volta alla istanziazione della portlet.
I metodi doView e processAction delegano l'elaborazione
al RicettarioController
Ricettario Controller
Vediamo
l'implementazione di questa classe in cui le dipendenze
sono iniettate da Spring (il IRicettaDao e l' IActionRequestTool)
/*
* Copyright 2000-2001,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the
"License");
* you may not use this file except in compliance with
the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in
writing, software
* distributed under the License is distributed on an
"AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
* See the License for the specific language governing
permissions and
* limitations under the License.
*/
/**
*@author Massimiliano Dessì
*@created 13 marzo 2005
*/
package org.casamia.cucina.ricettario.portlet;
import
java.io.IOException;
import
javax.portlet.*;
import
org.casamia.cucina.ricettario.db.dao.IRicettaDao;
import org.casamia.cucina.ricettario.portlet.util.IActionRequestTool;
import org.casamia.cucina.ricettario.util.Config;
import org.casamia.cucina.ricettario.vo.Ricetta;
public
class RicettarioController implements IRicettarioController
{
public void cleanUp() {}
/**
* Sets the ricettaDao attribute of the RicettarioController
object
*
*@param dao The new ricettaDao value
*/
public void setRicettaDao(IRicettaDao dao) {
_dao = dao;
}
/**
* Sets the requestTool attribute of the RicettarioController
object
*
*@param rt The new requestTool value
*/
public void setRequestTool(IActionRequestTool rt) {
_rt = rt;
}
/**
* Description of the Method
*
*@param request Description of the Parameter
*@param actionResponse Description of the Parameter
*/
public void processActionRequest(ActionRequest request,
ActionResponse actionResponse) {
String action = request.getParameter(_config.getAction());
if (action.equals(_config.getNuovaRicetta())) {
doNuova(request);
} else if (action.equals(_config.getInserimentoRicetta()))
{
doInsert(request);
} else if (action.equals(_config.getListaRicette()))
{
doLista(request);
} else if (action.equals(_config.getDettaglio())) {
doDetail(request);
} else if (action.equals(_config.getCancella())) {
doCancel(request);
} else if (action.equals(_config.getElimina())) {
doDelete(request);
} else if (action.equals(_config.getUpdate())) {
doUpdate(request);
} else if (action.equals(_config.getModifica())) {
doModify(request);
}
}
/**
* Description of the Method
*
*@param request Description of the Parameter
*@param response Description of the Parameter
*@param pc Description of the Parameter
*@exception PortletException Description of the Exception
*@exception IOException Description of the Exception
*/
public void processRenderRequest(RenderRequest request,
RenderResponse response, PortletContext pc)
throws PortletException, IOException {
PortletSession sess = request.getPortletSession();
if (null != sess.getAttribute(_config.getViewSwitch()))
{
handshake(sess, request);
} else {
request.setAttribute(_config.getRicetta(), _dao.getRicetta());
}
dispatch(pc, request, response);
}
/**
* Description of the Method
*
*@param sess Description of the Parameter
*@param request Description of the Parameter
*/
private void handshake(PortletSession sess, RenderRequest
request) {
request.setAttribute(_config.getViewSwitch(), sess.getAttribute(_config.getViewSwitch()));
sess.removeAttribute(_config.getViewSwitch());
request.setAttribute(_config.getModel(), sess.getAttribute(_config.getModel()));
sess.removeAttribute(_config.getModel());
}
/**
* Sets the modelAndView attribute of the RicettarioController
object
*
*@param session The new modelAndView value
*@param view The new modelAndView value
*@param nameModel The new modelAndView value
*@param model The new modelAndView value
*/
private void setModelAndView(PortletSession session,
String view,
String nameModel, Object model) {
session.setAttribute(_config.getViewSwitch(), view);
session.setAttribute(nameModel, model);
}
/**
* Sets the view attribute of the RicettarioController
object
*
*@param session The new view value
*@param view The new view value
*/
private void setView(PortletSession session, String
view) {
session.setAttribute(_config.getViewSwitch(), view);
}
/**
* Description of the Method
*
*@param pc Description of the Parameter
*@param req Description of the Parameter
*@param res Description of the Parameter
*@exception PortletException Description of the Exception
*@exception IOException Description of the Exception
*/
private void dispatch(PortletContext pc, RenderRequest
req,
RenderResponse res) throws PortletException, IOException
{
PortletRequestDispatcher rd = pc.getRequestDispatcher(_jspDispatcher);
rd.include(req, res);
}
/**
* Sets the jspDispatcher attribute of the RicettarioController
object
*
*@param jspView The new jspDispatcher value
*/
public void setJspDispatcher(String jspView) {
_jspDispatcher = jspView;
}
/**
* Sets the config attribute of the RicettarioController
object
*
*@param config The new config value
*/
public void setConfig(Config config) {
_config = config;
}
/**
* Sets the ricetta attribute of the RicettarioController
object
*
*@param ricetta The new ricetta value
*/
public void setRicetta(Ricetta ricetta) {
_ricetta = ricetta;
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doLista(ActionRequest req) {
setModelAndView(req.getPortletSession(), _config.getListaRicette(),
_config.getModel(), _dao.getRicette());
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doNuova(ActionRequest req) {
setView(req.getPortletSession(), _config.getNuovaRicetta());
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doCancel(ActionRequest req) {
String idRicetta = _rt.getId(req);
if (!idRicetta.equals(_config.getNonValorizzatoString()))
{
Ricetta vo = _dao.getRicetta(Integer.parseInt(req.getParameter(_config.getRicettaId())));
setModelAndView(req.getPortletSession(), _config.getCancella(),
_config.getModel(), vo);
}
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doDelete(ActionRequest req) {
String idRicetta = _rt.getId(req);
if (!idRicetta.equals(_config.getNonValorizzatoString()))
{
int risultato = _dao.eliminaRicetta(Integer.parseInt(idRicetta));
_rt.inserisciMessaggioDelete(req, risultato, Integer.parseInt(idRicetta));
}
doLista(req);
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doInsert(ActionRequest req) {
Ricetta ricetta = _rt.getRicetta(req);
if (null != ricetta) {
_rt.inserisciMessaggioInsert(req, _dao.inserisciRicetta(ricetta));
doLista(req);
} else {
_rt.inserisciMessaggioNoDati(req);
}
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doUpdate(ActionRequest req) {
Ricetta ricetta = _rt.getRicetta(req);
if (null != ricetta) {
_rt.inserisciMessaggioUpdate(req, _dao.aggiornaRicetta(ricetta));
} else {
_rt.inserisciMessaggioNoDati(req);
}
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doDetail(ActionRequest req) {
if (!_rt.getId(req).equals(_config.getNonValorizzatoString()))
{
Ricetta vo = _dao.getRicetta(Integer.parseInt(req.getParameter(_config.getRicettaId())));
setModelAndView(req.getPortletSession(), _config.getDettaglio(),
_config.getModel(), vo);
}
}
/**
* Description of the Method
*
*@param req Description of the Parameter
*/
private void doModify(ActionRequest req) {
if (!_rt.getId(req).equals(_config.getNonValorizzatoString()))
{
Ricetta vo = _dao.getRicetta(Integer.parseInt(req.getParameter(_config.getRicettaId())));
setModelAndView(req.getPortletSession(), _config.getModifica(),
_config.getModel(), vo);
}
}
private Config _config;
private Ricetta _ricetta;
private String _jspDispatcher;
private IActionRequestTool _rt;
private IRicettaDao _dao;
}
Nel
suo lavoro il Controller è coadiuvato da due
altre classi, una ActionRequestTool, che si occupa di
ricostruire gli oggetti prelevandoli dalla request.
Il secondo oggetto e l' oggetto Config valorizzato da
Spring e che contiene tutte le
configurazioni necessarie alla applicazione, infatti
non è presente una sola stringa "Hard coded".
Nel metodo processActionRequest, viene controllata l'azione
richiesta e dirottata sul metodo opportuno, una volta
eseguita l'elaborazione, il risultato viene messo nella
sessione della portlet. Quando verra fatto il rendering
con il doView, il metodo processRenderRequest controllerà
se nella PortletSession è stato messo qualche
oggetto da visualizzare.
Nel caso fosse presente, il metodo handshake provvede
a toglierlo dalla sessione e a metterlo nella request,
in modo da renderlo disponibile nelle jsp , ma anche
per non appesantire la sessione. Gli oggetti (ricetta.model),
potrebbero essere presi nella jsp anche dalla sessione
con un RenderRequest.getPortletSession().getAttribute()
, ma rimarrebbero comunue inutilmente nella sessione
della portlet.
Se invece il processRenderRequest non trova niente che
gli indichi la presenza di oggetti, mostra semplicemente
la ricetta nella visualizzazione ordinaria che deve
essere mostrata in quel momento.
Figura 5 - IActionRequestTool
Figura 6 - Config
Visualizzazione
Ci
ritroviamo a dover visualizzare vari stati di funzionamento,
partendo però dal presupposto che una portlet
secondo le specifiche Portlet 1.0 (jsr 168) ha una jsp
per la view, una per l' edit e una per l' help.
Scegliamo quindi di avere una jsp che agisce da dispatcher
secondo quanto dettato da ciò che
viene settato nel metodo setModelAndView nel RicettarioController
.
JspDispatcher.jsp
<%--
Copyright 2004 The Apache Software Foundation
Licensed
under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with
the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless
required by applicable law or agreed to in writing,
software
distributed under the License is distributed on an "AS
IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
See the License for the specific language governing
permissions and
limitations under the License.
--%>
<%@ taglib uri='/WEB-INF/tld/c.tld' prefix='c'%>
<c:choose>
<c:when test="${v_switch == 'ricetta.list'}">
<jsp:include page="lista.jsp"/>
</c:when>
<c:when test="${v_switch eq 'ricetta.new'}">
<jsp:include page="nuova.jsp"/>
</c:when>
<c:when test="${v_switch eq 'ricetta.detail'}">
<jsp:include page="dettaglio.jsp"/>
</c:when>
<c:when test="${v_switch eq 'ricetta.modify'}">
<jsp:include page="modifica.jsp"/>
</c:when>
<c:when test="${v_switch eq 'ricetta.cancel'}">
<jsp:include page="cancel.jsp"/>
</c:when>
<c:otherwise>
<jsp:include page="viewOrdinary.jsp"/>
</c:otherwise>
</c:choose>
La vista normale sarà
<%--
Copyright 2004 The Apache Software Foundation
Licensed
under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with
the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless
required by applicable law or agreed to in writing,
software
distributed under the License is distributed on an "AS
IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
See the License for the specific language governing
permissions and
limitations under the License.
--%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<%@ taglib uri='/WEB-INF/tld/c.tld' prefix='c'%>
<%@ taglib uri='/WEB-INF/tld/c-rt.tld' prefix='c-rt'%>
Ricettario
portlet
<portlet:defineObjects/>
<DIV style="position:relative">
<a href="<portlet:actionURL>
<portlet:param name="azione" value="ricetta.list"/>
</portlet:actionURL>"><font color="#FD0A11">Lista
Ricette</font></a>
</DIV>
<table
width="458" border="0" cellspacing="0"
cellpadding="0">
<tr>
<td width="458" align="left"
valign="top" background="images/colore_interna.gif"
class="contentarticoli">
<p><img src="/ricettario/images/1.jpg"
width="150" height="150" hspace="3"
vspace="o" align="right">
<strong><c:out value="${ricetta.nome}"/></strong><br><br>
<p><b>Per <c:out value="${ricetta.numeroPersone}"/></b></p>
<p><b>Ingredienti:</b><c:out value="${ricetta.descrizione}"/></p>
<p><b>Preparazione</b><br><c:out
value="${ricetta.preparazione}"/></p>
</p> </td>
</tr>
</table>
Figura 7 - Vista ordinaria
La lista invece sarà :
lista.jsp
<%--
Copyright 2004 The Apache Software Foundation
Licensed
under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with
the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless
required by applicable law or agreed to in writing,
software
distributed under the License is distributed on an "AS
IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
See the License for the specific language governing
permissions and
limitations under the License.
--%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<%@ taglib uri='/WEB-INF/tld/c.tld' prefix='c'%>
<%@ taglib uri='/WEB-INF/tld/c-rt.tld' prefix='c-rt'%>
<%@ page import="org.casamia.cucina.ricettario.vo.Ricetta"%>
<portlet:defineObjects/>
<portlet:renderURL portletMode="view" var="normal"/>
<a href='<%=normal%>'>Vista Ordinaria Utente</a>
<c-rt:set
var="ricette" value="<%=renderRequest.getAttribute("ricetta.model")%>"/>
<c:forEach
var="ricetta" items="${ricette}"
varStatus="status"><br><br>
<%
Ricetta ric =(Ricetta)pageContext.getAttribute("ricetta");
String id = String.valueOf(ric.getId());
String nome= ric.getNome();
%>
<%=nome%>
<a href="<portlet:actionURL>
<portlet:param name="azione" value="ricetta.detail"/>
<portlet:param name="ricetta.id" value="<%=id%>"/>
</portlet:actionURL>">Visualizza</font>
<a href="<portlet:actionURL>
<portlet:param name="azione" value="ricetta.modify"/>
<portlet:param name="ricetta.id" value="<%=id%>"/>
</portlet:actionURL>">Modifica</font>
<a href="<portlet:actionURL>
<portlet:param name="azione" value="ricetta.cancel"/>
<portlet:param name="ricetta.id" value="<%=id%>"/>
</portlet:actionURL>">Elimina</a>
</c:forEach>
<br><br><br>
<a
href="<portlet:actionURL>
<portlet:param name="azione" value="ricetta.new"/>
</portlet:actionURL>"><font color="#FD0A11">Nuova
Ricetta</font></a>
Figura 8 - Lista ricette
Figura 9 - Modifica ricetta
Figura 10 - Conferma eliminazione ricetta
Dominio
dati
Il modello dei dati è la Ricetta
Figura 11 - Ricetta
Configurazione
Una volta compilate le classi e scritte le nostre jsp,dobbiamo
scrivere tre file di configurazione,
un web.xml come tutte le web-app, un portlet.xml, un
jetspeed-portlet.xml e modificare il default.psml
per dire a jetspeed dove la vogliamo vedere (nella pagina
di default)
Portlet.xml
<?xml
version="1.0" encoding="UTF-8"?>
<portlet-app id="ricettario" version="1.0">
<portlet id="Ricettario">
<portlet-name>Ricettario</portlet-name>
<display-name>Ricettario</display-name>
<description>Ricettario</description>
<portlet-class>org.casamia.cucina.ricettario.portlet.RicettarioPortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Ricettario</title>
<short-title>Ricettario</short-title>
<keywords>Ricettario</keywords>
</portlet-info>
</portlet>
</portlet-app>
Jetspeed-portlet.xml
<?xml
version="1.0" encoding="UTF-8"?>
<portlet-app
id="ricettario" version="1.0" xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
xmlns:js="http://portals.apache.org/jetspeed"
xmlns:dc="http://www.purl.org/dc">
<portlet>
<portlet-name>Ricettario</portlet-name>
<dc:title>Ricettario</dc:title>
<dc:creator>Massimiliano Dessì</dc:creator>
</portlet>
</portlet-app>
default.psml:
aggiungiamo
in coda la nostra portlet
...
<fragment id="dp-30" type="portlet"
name="ricettario::Ricettario">
<property layout="TwoColumns" name="row"
value="4" />
<property layout="TwoColumns" name="column"
value="1" />
</fragment>
</fragment>
Beans.xml
Vediamo
le mappature degli oggetti aggiunti in questo articolo
rispetto al precedente
<?xml
version="1.0" encoding="UTF-8"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed
under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with
the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless
required by applicable law or agreed to in writing,
software
distributed under the License is distributed on an "AS
IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.
See the License for the specific language governing
permissions and
limitations under the License.
-->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
...
<!-- RicettarioController -->
<bean id="ricettarioController" class="org.casamia.cucina.ricettario.portlet.RicettarioController">
<property name="ricettaDao"><ref
bean="ricettaJdbcClassic"/></property>
<property name="jspDispatcher"><value>/jsp/dispatcher.jsp</value></property>
<property name="requestTool"><ref
bean="art"/></property>
<property name="config"><ref bean="config"/></property>
<property name="ricetta"><ref bean="ricetta"/></property>
</bean>
<!--
ActionRequestTool -->
<bean id="art" class="org.casamia.cucina.ricettario.portlet.util.ActionRequestTool">
<property name="config"><ref bean="config"/></property>
<property name="msgIncomplete"><value>Inserire
tutti i dati della ricetta</value></property>
<property name="msgInsertOk"><value>La
ricetta è stata inserita</value></property>
<property name="msgInsertNo"><value>La
ricetta non è stata inserita</value></property>
<property name="msgUpdateOk"><value>La
ricetta è stata aggiornata</value></property>
<property name="msgUpdateNo"><value>La
ricetta non è stata aggiornata</value></property>
<property name="msgDeleteOk"><value>E'
stata eliminata la ricetta con id:</value></property>
<property name="msgDeleteNo"><value>Non
è' stata eliminata la ricetta con id:</value></property>
<property name="ricetta"><ref bean="ricetta"/></property>
</bean>
<!-- Ricetta -->
<bean id="ricetta" class="org.casamia.cucina.ricettario.vo.Ricetta">
<constructor-arg type="java.lang.String"><value>Campo
non valorizzato</value></constructor-arg>
<constructor-arg type="int"><value>0</value></constructor-arg>
</bean>
<!-- Config -->
<bean id="config" class="org.casamia.cucina.ricettario.util.Config">
<property name="action"><value>azione</value></property>
<property name="cancella"><value>ricetta.cancel</value></property>
<property name="contentType"><value>text/html</value></property>
<property name="descrizioneReq"><value>ricetta.descrizione</value></property>
<property name="dettaglio"><value>ricetta.detail</value></property>
<property name="elimina"><value>ricetta.delete</value></property>
<property name="inserimentoRicetta"><value>ricetta.new.insert</value></property>
<property name="listaRicette"><value>ricetta.list</value></property>
<property name="messaggio"><value>messaggio</value></property>
<property name="modifica"><value>ricetta.modify</value></property>
<property name="nomeController"><value>ricettarioController</value></property>
<property name="nomeRicettaReq"><value>ricetta.nome</value></property>
<property name="nonValorizzatoString"><value>Campo
non valorizzato</value></property>
<property name="numeroPersoneReq"><value>ricetta.numero.persone</value></property>
<property name="nuovaRicetta"><value>ricetta.new</value></property>
<property name="preparazioneReq"><value>ricetta.preparazione</value></property>
<property name="ricetta"><value>ricetta</value></property>
<property name="idRicetta"><value>ricetta.id</value></property>
<property name="servizio"><value>servizio</value></property>
<property name="update"><value>ricetta.update</value></property>
<property name="viewSwitch"><value>v_switch</value></property>
<property name="model"><value>ricetta.model</value></property>
</bean>
Documentazione
dinamica del beans.xml generata con Spring BeanDoc
Figura 12 - Spring beandoc
Figura 13 - Spring beandoc
Una
volta impacchettato il tutto in un file war, poniamo
il war nella cartella WEB-INF\deploy di Jetspeed e fatta
ripartire l' applicazione, ci ritroveremo la nostra
portlet.
Conclusioni
In questa articolo abbiamo visto come portare su Jetspeed
2 una portlet funzionante su Jetspeed 1, usando la M2
di Jetspeed 2 con tomcat 5.0.30, e Spring 1.2 RC1. Sul
prossimo articolo vedremo e confronteremo il servizio
che esegue la rotazione delle varie ricette usando MX4J,
e le nuove features di supporto a Jmx introdotte nella
versione 1.2 di Spring.
Vedremo anche la struttura del database sottostante.
In seguito vedremo come integrare una applicazione interamente
Spring MVC dentro Jetspeed2.
Riferimenti
Apache
Portals: http://portals.apache.org
Jetspeed 2: http://portals.apache.org/jetspeed-2/
Spring framework: http://www.springframework.org
Jetspeed
2 parte Seconda: http://www.jugsardegna.org/vqwiki/jsp/Wiki?Jetspeed2_I
Jetspeed 2 parte Prima: http://www.jugsardegna.org/vqwiki/jsp/Wiki?Jetspeed2
Portlet III JSR 168: http://www.mokabyte.it/2003/09/jportlet-3.htm
Spring e IoC : http://www.jugsardegna.org/vqwiki/jsp/Wiki?SpringIoCJet2
Bibliografia
J2ee Development without EJB: Rod Johnson, Juergen Hoeller
Ed. Wrox
Pro Spring: Rob Harrop, Jan Machacek Ed.Apress
Spring in Action :Craig Walls, Ryan Breidenbach Ed.
Manning
Sviluppo
Pluto eclipse: http://plutoeclipse.sourceforge.net/
Spring BeanDoc: http://opensource.atlassian.com/confluence/spring/display/BDOC/Home
Omondo EclipseUML: http://www.omondo.com/download/index.html
Graphviz: http://www.graphviz.org/
Massimiliano
Dessì (http://www.jugsardegna.org/vqwiki/jsp/Wiki?MassimilianoDessi)
ha iniziato a lavorare presso la Sistemi informativi
(Società IBM) come programmatore Java. Dal 2001
lavora presso Atlantis S.p.A., dove utilizzando metodologie
agili quali l'eXtreme programming (Xp), sviluppa applicazioni
enterprise Web-based con tecnologia J2EE quali portali
e content management system per la promozione del territorio.
Nel poco tempo libero, cura la versione italiana di
Jetspeed, tiene seminari e corsi su tecnologie J2EE
e collabora con società e enti italiani ed esteri
per la realizzazione di portali J2EE, è studente
di Ingegneria Informatica al Politecnico di Torino.
|