MokaByte 96 - Maggio 2005
  MokaByte 96 - Maggio 2005  

 

 

 

Jetspeed2
III parte

In questo articolo continueremo l'analisi di una applicazione J2EE funzionante in Jetspeed 2,
costruita in manierà ancora più Spring / Ioc oriented rispetto al precedente articolo.
Tutte le classi che la compongono eccetto una, sono infatti costruite in maniera tale da avere le dipendenze iniettate da Spring. Viene inoltre presa a modello per la visualizzazione, l'architettura di Spring MVC, e viene usato il tool Spring BeanDoc per la documentazione dinamica dei file di configurazione di Spring

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.