martedì 27 dicembre 2011

Gestire permessi per i file da terminale

Esistono 3 permessi attribuibili a un file o directory (per Ubuntu sono la stessa cosa):
  • r  che sta per read
  • x che sta per execute
  • w che sta per write
Esistono poi 3 tipologie di utenti:
  • Proprietario indicato con la lettera u
  • Gruppo indicato con la lettera g
  • Altri indicati con la lettera o

Se creiamo in una directory due file di testo (es. f1.txt e f2.txt) e poi scriviamo
ls -l  sul terminale (ossi elenca file e permessi)
otteniamo un risultato di questo tipo:

-rw-rw-r-- 1 carlo carlo 0 2011-12-28 00:10 f1.txt
-rw-rw-r-- 1 carlo carlo 0 2011-12-28 00:09 f2.txt


Il primo carattere ci dice se si tratta di un file o di una directory , se è un file compare il carattere - altrimenti la lettera d.
In questo caso, essendo 2 file abbiamo 2 -.
Il prosieguo della stringa si legge a gruppi di 3 e indica i permessi del proprietario del gruppo e degli altri utenti.
Quindi la stringa sopra incollata significa che per i 2 file il proprietario ha diritti di read e write  così come l'utente Gruppo.
Gli "altri" hanno solo il privilegio di lettura.
Per aggiungere/togliere permessi si utilizza il comando chmod con sintassi

chmod [tipo_utente] +/- [permessi] [nome_file_o_directory]

Esempio: aggiungere permesso di esecuzione all'utente Proprietario

chmod u+x f1.txt

Se richiediamo ls -l abbiamo adesso:

-rwxrw-r-- 1 carlo carlo    0 2011-12-28 00:10 f1.txt


Per togliere il permesso di lettura all'utente "Altri"


chmod o-r f1.txt

 Se richiediamo ls -l abbiamo adesso:

 -rwxrw---- 1 carlo carlo    0 2011-12-28 00:10 f1.txt







Leggere File di Properties settandone i parametri

Supponiamo di avere un file di Properties con nel messaggio dei placeholder, che servono per inserire testo dinamico a completamento.

Esempio il file test.properties così composto:

test=ciao {0} il tuo cognome è {1}


Per leggere il file ed effettuare la sostituzione dei parametri si utilizza la classe MessageFormat.

Properties p=new Properties();
p.load(new FileInputStream(("out/test.properties")));
System.out.println(MessageFormat.format(p.getProperty("test"), "Mario","Rossi"));


L'output sarà :

ciao Mario il tuo cognome è Rossi

Per versioni precedenti di Java come Java 4 si può utilizzare il metodo:

MessageFormat.format(p.getProperty("test"), new Object[]{"Mario","Rossi"})

domenica 25 dicembre 2011

Esempio utilizzo MDB

Nel seguente esempio proviamo a :
  • Definire una coda JMS su Jboss 5.1;
  • Realizzare un programma client java che scriva sulla coda dei messaggi;
  • Realizzare un Message Driven Bean che legga il messaggio e lo tolga dalla coda JMS.
DEFINIRE CODA JMS

Sotto la directory default deploy creare una directory denominata code dove andremo a definire la nostra coda JMS.

A questo punto dalla console di amministrazione di Jboss (utenza e pwd di default sono admin admin).




Cliccando su Add a new Resource e seguendo il menu definiamo il nome della coda "MiaCoda" e il JNDI name "code/MiaCoda".
Una volta terminata la procedura possiamo verificare il corretto funzionamento guardando sotto la directory deploy/code, troveremo il file xml MiaCoda-service.xml.

DEFINIRE CLIENT JAVA

Definiamo un semplice progetto Java su eclipse, inserendo nel classpath tutte le librerie presenti nella directory client di Jboss.

Il codice nel main del programma è il seguente:

import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;

public class MessageSender {

   
   
    public static void main(String[] args) throws Exception{
        ConnectionFactory connectionFactory;
        Destination destination;
        Properties p=new Properties();
        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
        p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
        p.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
        Context ctx=new InitialContext(p);
        connectionFactory=(ConnectionFactory)ctx.lookup("/ConnectionFactory");
        destination=(Queue)ctx.lookup("/code/MiaCoda");
        System.out.println("La coda e la connessione sono stati recuperati");
        Connection connection=null;
        connection=connectionFactory.createConnection();
        Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer mp=session.createProducer(destination);
         TextMessage msg = session.createTextMessage();
          for (int i = 0; i < 5; i++) {
          msg.setText("Questo è il messaggio " + (i + 1));
          mp.send(msg);
          }
          connection.close();
          System.out.println("Messaggi inviati correttamente");
         
    }
   
}


Vengono scritti e inviati 5 messaggi.
Se proviamo ad eseguire il programma con Jboss acceso vediamo che da Console ci compare il seguente messaggio:

La coda e la connessione sono stati recuperati
Messaggi inviati correttamente


Quindi andando sulla console di amministrazione di Jboss in corrispondenza della coda "MiaCoda" troviamo:

Vediamo che risultano 0 consumer (nessuno ha letto i messaggi, non essendoci ancora l'MDB) e 5 messaggi presenti nella coda.




DEFINIRE IL MESSAGE DRIVEN BEAN

L' MDB ha il compito di connettersi alla coda e leggere i messaggi presenti.
Per realizzarlo creiamo un progetto Java inserendo nel classpath le librerie client di Jboss 5.1.
Per definire l'MDB annotiamo la classe con @MessageDriven, mentre la classe deve implementare l'interfaccia MessageListener (del package javax.jms).
Da notare la definizione dell'elemento activationConfig dove si specifica il tipo di Destination (in questo caso una coda) e il nome della coda ("code/MiaCoda").

Il codice è il seguente:

import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(name="MessageBean",
activationConfig= {
        @ActivationConfigProperty(propertyName="destinationType",
                                    propertyValue="javax.jms.Queue"),
        @ActivationConfigProperty(propertyName="destination",
                                    propertyValue="code/MiaCoda")
                  }
        )

public class MessageBean implements MessageListener {
    @Resource
       private MessageDrivenContext mdc;

     
       public void onMessage(Message msg) {
         TextMessage tmsg = null;

       try
       {
             tmsg = (TextMessage) msg;
             System.out.println("MESSAGE BEAN: Messaggio ricevuto: " + tmsg.getText( ));
             System.out.println ("Metodo onMessage() richiamato");
       }
       catch (JMSException e) {
                               e.printStackTrace( );
                               mdc.setRollbackOnly( );
                              }
      catch (Throwable th)    {
                              th.printStackTrace();
                              }
       }
     
}


Una volta fatto ciò possiamo esportare il progetto come jar file all'interno della directory deploy di JBoss.

Una volta deployato subito si nota sulla console di Jboss che i messaggi messi nella coda sono stati consumati dall'MDB:


13:06:53,945 INFO  [STDOUT] MESSAGE BEAN: Messaggio ricevuto: Questo è il messaggio 2
13:06:53,945 INFO  [STDOUT] Metodo onMessage() richiamato
13:06:53,946 INFO  [STDOUT] MESSAGE BEAN: Messaggio ricevuto: Questo è il messaggio 3
13:06:53,946 INFO  [STDOUT] Metodo onMessage() richiamato
13:06:53,947 INFO  [STDOUT] MESSAGE BEAN: Messaggio ricevuto: Questo è il messaggio 1
13:06:53,947 INFO  [STDOUT] Metodo onMessage() richiamato
13:06:53,947 INFO  [STDOUT] MESSAGE BEAN: Messaggio ricevuto: Questo è il messaggio 4
13:06:53,948 INFO  [STDOUT] Metodo onMessage() richiamato
13:06:53,949 INFO  [STDOUT] MESSAGE BEAN: Messaggio ricevuto: Questo è il messaggio 5
13:06:53,950 INFO  [STDOUT] Metodo onMessage() richiamato


Andando sulla coda via console di amministrazione vediamo infatti che adesso il Campo Consumer count è pari a 1 mentre il Message Count a 0.
Tutti i messaggi sono stati letti quindi dall'MDB e la coda è stata svuotata.

SCRIVERE MESSAGGI SULLA CODA JMS VIA WEB APPLICATION

In questo caso realizziamo una semplice Web appplication con un form su cui si inserisce il messaggio in una textArea e si invia il tutto ad una servlet che si occupa di aggiungere il messaggio alla coda jms.
Si noti come in questo caso i riferimenti alla ConnectionFactory e alla Destination siano recuperati tramite l'annotazione @Resource e non tramite look up JNDI.

public class ScriviMessaggioSuCoda extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Resource(name="code/MiaCoda",mappedName="code/MiaCoda")
    private javax.jms.Destination codaTest;
    @Resource(name="ConnectionFactory",mappedName="ConnectionFactory")
    private javax.jms.ConnectionFactory connentionFactory;
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ScriviMessaggioSuCoda() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        try
        {
        String messaggio=request.getParameter("txtMessage");
        Connection connection = connentionFactory.createConnection();
          connection=connentionFactory.createConnection();
        Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer mp=session.createProducer(codaTest);
        TextMessage msg = session.createTextMessage();
        msg.setText(messaggio);
        mp.send(msg);
        connection.close();
        System.out.println("Sending message");
        session.close ();
        PrintWriter wr=response.getWriter();
        wr.write("<b>Messaggio inviato</b>");
        wr.flush();
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
         
       
    }

}

venerdì 23 dicembre 2011

Progetto di test Junit su Eclipse

Per creare un semplice progetto di Junit test su eclipse occorre:
  • Scaricarsi la libreria Junit da qui;
  • Inserire il jar di Junit nella lib del progetto e aggiungerla al classpath;
  • Scrivere una classe java che estenda la classe junit.framework.TestCase;
  • Definire una serie di metodi void con firma public void testXXXX();
  • Lanciare la classe scegliendo tra le opzioni run as Junit-test
Nel mio caso ad esempio volevo testare un metodo per la validazione della partita iva.
Ho preso quindi delle partite iva corrette e alcune sbagliate, scrivendo un metodo di questo tipo:

public void testPartitaIva(){
  PartitaIva p=PartitaIva.getInstance();
  System.out.println("Inizio test partita iva...");
  assertEquals(true, p.verificaPartitaIva("07973780013"));
  assertEquals(true, p.verificaPartitaIva("00875591000"));
  assertEquals(true, p.verificaPartitaIva("13212880150"));
  assertEquals(true, p.verificaPartitaIva("04914190824"));
  assertEquals(true, p.verificaPartitaIva("00905811006"));
  assertEquals(false, p.verificaPartitaIva("00905811007"));
  assertEquals(false, p.verificaPartitaIva("04914190825"));
  assertEquals(false, p.verificaPartitaIva("13212880151"));
  assertEquals(false, p.verificaPartitaIva("00875591009"));
  assertEquals(false, p.verificaPartitaIva("07973780016"));
  System.out.println("Partita iva ok");
       
    }


Eseguendolo come test Junit sulla console di Eclipse nel caso in cui non ci siano errori appare la seguente schermata:



mercoledì 21 dicembre 2011

Calcolare l'Md5 di una stringa

Un metodo statico per il calcolo dell'hash di una Stringa (MD5).


/**
  * Calcola l'hash
  * @param md5 la stringa in ingresso
  * @param encoding l'encoding (es utf-8,latin1...)
  * @return
  * @throws UnsupportedEncodingException
  */
 public static String MD5(String md5,String encoding) throws UnsupportedEncodingException {  
  try {        
   java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
   String s=new String(md5.getBytes(), encoding);
   byte[] array = md.digest(s.getBytes());       
   StringBuffer sb = new StringBuffer();       
   for (int i = 0; i < array.length; ++i) { 
    String hex=Integer.toHexString((array[i] & 0xFF)+0x100).substring(1);
    sb.append(hex);
   }        
   return sb.toString();     }
  catch (java.security.NoSuchAlgorithmException e) {   
   throw new IllegalArgumentException("Attenzione non esiste l'algoritmo di cifratura selezionato");
  }   
 } 


Ottenere informazioni sulla locazione di un War a runtime

Per conoscere esattamente il percorso completo (che varia da Sistemi Operativi ad Application Server) della context root della nostra web app a runtime è sufficiente eseguire il seguente codice sulla jsp:

<%ServletContext ctx=getServletContext(); %

Esempio risultati, su una web app deployata su jboss:

C:\ApplicationServers\jboss-5.1.0.GA\server\default\tmp\a6d6hk-yat7vh-gwg691ss-1-gwg69t38-9p\WebTest.war 
<%=ctx.getRealPath("") %>
>

mercoledì 14 dicembre 2011

Limitare via javascript il numero caratteri inseriti su textarea

Con questo javascript è possibile data una textarea limitare l'input dei caratteri inseriti avvisando l'utente di quanti caratteri stia inserendo (esponendogli il messaggio in una input text hidden).

Il javascript è il seguente:

function contaCaratteri(area, field, max){
    var cont= area.value.length;
    if (cont > max){
        area.value = area.value.substr(0, max);
       
        document.getElementById(field).value = 'Massimo ' + max + ' caratteri!';
      
       
       
      
    }else{
        if(cont>1){
        document.getElementById(field).value = 'Inseriti ' + cont + ' caratteri!';
        }
        else
        {
            document.getElementById(field).value = 'Inserito ' + cont + ' carattere!';
        }
    }
}


L'esempio HTML è questo (digitare all'interno della textarea):



venerdì 9 dicembre 2011

Lista dati con checkbox usando display tag

Con riferimento al post precedente vediamo lo stesso esempio fatto con display-tag.
In questo caso l'unica cosa poco carina mi sembra sia il fatto che per mostrare nell'header la checkbox che consente di fare i check e decheck massivi bisogna scrivere nel title direttamente l'html.

Ecco l'esempio:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
   
<%@taglib uri="http://displaytag.sf.net" prefix="display" %>
 <%@taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div >
<form name="myForm" action="VisualizzaRisultati" method="post">

     <display:table name="sessionScope.lista"   cellspacing="0"
             id="r" >
       <display:column title="<input type='checkbox' name='selectall' onclick='javascript:checkDececkAll()' />" sortable="false" media="html">
     
       
        <input type="checkbox" name="idValue"  ${r.checked}/>
        <input type="hidden" name="txtValore" value=""/>
       </display:column>
       <display:column property="dataCreation" title="Data creazione"></display:column>
       <display:column property="location" title="Location"></display:column>
       <display:column property="name" title="Nome"></display:column>
       <display:column property="status" title="Status"></display:column>
     </display:table>
     <input type="button" name="InvioDati" value="Invia" onclick="javascript:invio()"/>
</form>
   </div>
</body>
<script language="javascript">
var checked=false;
function checkDececkAll()
{
    var field=document.myForm.idValue;
   
    if(checked){
        // uncheck
        for (var i = 0; i < field.length; i++){
            field[i].checked = false ;
        }
        checked=false;
    }
    else
        {
          //check
        for (var i = 0; i < field.length; i++){
            field[i].checked = true ;
        }
         checked=true;
    }
    }
function invio(){
    var field=document.myForm.idValue;
    var txt=document.myForm.txtValore;
    for(var i=0;i<field.length;i++){
        if(field[i].checked){
            field[i].value="ok";
            txt[i].value="ok";
        }
        else
            {
            field[i].value="ko";
            txt[i].value="ko";
            }
    }
    document.myForm.submit();
}
</script>
</html>

Lista dati con checkbox e possibilità di selezionare tutti gli elementi

E' questa una delle più classiche attività che capita fare sviluppando applicativi (in special modo gestionali).
Visualizziamo dei dati da una lista e li esponiamo a video , l'utente può quindi selezionarle tutte o nessuna o quelle che vuole lui e premendo il tasto invio dobbiamo inviare i dati, distinguendo tra selezionati e no.

Vediamo un immagine di esempio:

Vediamo come realizzarlo utilizzando jsp e jstl.
Lato javascript al momento dell'invio del form parte un evento che per ogni check selezionato va a settare un valore "ok" in un campo hidden.
Questo perchè lato server come parameter passeranno soltanto le check selezionate e a noi serve sapere per ogni elemento sia se è stato selezionato che se non lo è stato.


Ecco la jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
 <%@taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form name="myForm" action="VisualizzaRisultati" method="post">
<table border="1">
<tr>
<td><input type="checkbox" name="chkAll" onclick="javascript:checkDececkAll()"/></td>
<td>Nome</td>
<td>Luogo</td>
<td>Status</td>
<td>Data</td>
</tr>
<c:forEach var="item" items="${lista}">
        <tr> 
              <td>
                  <input type="checkBox" name="idValue" id="idValue" value="ko" ${item.checked}>   
                  <input type="hidden" name="txtValore" value=""/>             
              </td>   
            <td>${item.name}</td>
            <td>${item.location}</td>
            <td>${item.status}</td>
            <td>${item.dataCreation}</td>
            </tr>       
    </c:forEach>
</table>
    <br>
    <input type="button" onclick="javascript:invio()" value="Prova"/>
    </form>
</body>

<script language="javascript">
var checked=false;
function checkDececkAll()
{
    var field=document.myForm.idValue;
    if(checked){
        // uncheck
        for (var i = 0; i < field.length; i++){
            field[i].checked = false ;
        }
        checked=false;
    }
    else
        {
          //check
        for (var i = 0; i < field.length; i++){
            field[i].checked = true ;
        }
         checked=true;
    }
    }
function invio(){
    var field=document.myForm.idValue;
    var txt=document.myForm.txtValore;
    for(var i=0;i<field.length;i++){
        if(field[i].checked){
            field[i].value="ok";
            txt[i].value="ok";
        }
        else
            {
            field[i].value="ko";
            txt[i].value="ko";
            }
    }
    document.myForm.submit();
}

</script>
</html>


Per gestire invece i valori lato server possiamo procedere in questo modo:


    List<Item> liste=(List<Item>)request.getSession().getAttribute("lista");
        String[] parametri=request.getParameterValues("txtValore");
        for(int i=0;i<parametri.length;i++){
            liste.get(i).setSelezionato((parametri[i].equals("ok")?true:false));
            liste.get(i).setChecked(parametri[i].equals("ok")?"checked":"");
        }
        request.getSession().setAttribute("lista", liste);
        RequestDispatcher rd=request.getRequestDispatcher("jsp/listaChkBox.jsp");
        rd.forward(request, response);



lunedì 5 dicembre 2011

Java esempio utilizzo JFreeChart

In questo post vediamo come generare un semplice grafico usando la libreria JFreeChart ( http://www.jfree.org/jfreechart/ ).
Partiamo da una jsp e inseriamo i dati di vendita di 3 soggetti, quindi invochiamo una servlet che utilizzando JFreeChart crea l'oggetto grafico scrivendolo come immagine png e rinviandola al client.

La jsp è un semplice form con 3 textBox in cui inserire i dati:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form name="generateChart" method="post" action="Disegna">
<table>
<tr>
<td>Mario:</td><td><input type="text" id="txtMario" name="txtMario"/></td>
</tr>
<tr>
<td>Gino:</td><td><input type="text" id="txtGino" name="txtGino"/></td>
</tr>
<tr>
<td>Pino:</td><td><input type="text" id="txtPino" name="txtPino"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" name="btnInvio" value="Genera Grafico"/></td>
</tr>
</table>
</form>
</body>
</html>




La servlet è la seguente:

package it.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
/**
 * Servlet implementation class FreeChartGenerator
 */
public class FreeChartGenerator extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FreeChartGenerator() {
        super();
        // TODO Auto-generated constructor stub
    }

    private JFreeChart getGrafico(double[] lista) 
    {
        String[] series=new String[]{"Mario","Gino","Pino"};
        DefaultCategoryDataset cds=new DefaultCategoryDataset();
        for(int i=0;i<lista.length;i++){
            cds.addValue(lista[i], "", series[i]);
        }
   
     JFreeChart hitsByFolderChart = ChartFactory.createBarChart( "Report
 Vendite", "Venditore", "Euro", cds, PlotOrientation.HORIZONTAL, false, 
false, false );
        
        return hitsByFolderChart;
//    
        
        
    }
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        double d1=Double.valueOf(request.getParameter("txtMario"));
        double d2=Double.valueOf(request.getParameter("txtGino"));
        double d3=Double.valueOf(request.getParameter("txtPino"));
        double[] ld=new double[3];
        ld[0]=d1;
        ld[1]=d2;
        ld[2]=d3;
        JFreeChart chart=getGrafico(ld);
        response.setContentType("image/png");
        
        ChartUtilities.writeChartAsJPEG(response.getOutputStream(), chart, 500, 300);
        
    }

}




Il risultato finale, dopo aver inserito i seguenti dati sulla jsp:





Sarà il seguente:





domenica 4 dicembre 2011

Java generare un excel da una servlet

Tipicamente si richiede di esportare in formato excel o pdf dati provenienti da liste presenti a front end.
Una soluzione automatica e veloce per questo è utilizzare la libreria dispay tag.
Se però le richieste sono più articolate è necessario utilizzare librerie ad hoc.
Nell'esempio seguente  ci sono due liste diverse di dati (libri e persone) e si vuole vederle raggruppate in un unico excel.

In questo esempio vediamo come generare un excel con, sullo stesso foglio, prima i dati di una lista e poi dell'altra, frapponendo tra le due liste una riga vuota.
Per farlo ho utilizzato le librerie di Apache POI, già viste in altri post.

Il metodo doPost della servlet è il seguente:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try
        {
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment; filename=\""
                        + "export.xls" + "\"");
            ServletOutputStream out = response.getOutputStream();
            HSSFWorkbook wb=getExcel();
            wb.write(out);
            out.close();
        }
        catch(Exception ex){
            ex.printStackTrace();       
        }   
    }


L'oggetto HSSFWorkbook è così creato:

    private HSSFWorkbook getExcel() throws Exception{
        HSSFWorkbook workbook = new HSSFWorkbook();
        // qui si caricano i dati (es. da db) delle due liste persone e libri
        List<Persona> persone=getPersone();
        List<Libro> libri=getLibri();
        HSSFSheet firstSheet = workbook.createSheet("LISTE");
        // riga intestazione prima lista
        HSSFRow rowA = firstSheet.createRow(0);
        HSSFCell cellA = rowA.createCell(0);
        cellA.setCellValue(new HSSFRichTextString("Nome"));
        HSSFCell cellB = rowA.createCell(1);
        cellB.setCellValue(new HSSFRichTextString("Cognome"));
        HSSFCell cellC = rowA.createCell(2);
        cellC.setCellValue(new HSSFRichTextString("Eta'"));
        int i=1;
        for(Persona p:persone){
            HSSFRow riga=firstSheet.createRow(i);
            HSSFCell cellaNome=riga.createCell(0);
            cellaNome.setCellValue(new HSSFRichTextString(p.getNome()));
            HSSFCell cellaCognome=riga.createCell(1);
            cellaCognome.setCellValue(new HSSFRichTextString(p.getCognome()));
            HSSFCell cellaEta=riga.createCell(2);
            cellaEta.setCellValue(new HSSFRichTextString(String.valueOf(p.getEta())));
            i++;
           
        }
        // riga vuota
        HSSFRow rigaVuota=firstSheet.createRow(i);
        i++;
        // riga intestazione nuova lista
        HSSFRow rowLibro = firstSheet.createRow(i);
        HSSFCell cellAutore = rowLibro.createCell(0);
        cellAutore.setCellValue(new HSSFRichTextString("Autore"));
        HSSFCell cellTitolo = rowLibro.createCell(1);
        cellTitolo.setCellValue(new HSSFRichTextString("Titolo"));
        HSSFCell cellPrezzo = rowLibro.createCell(2);
        cellPrezzo.setCellValue(new HSSFRichTextString("Prezzo"));
        HSSFCell cellCodice = rowLibro.createCell(3);
        cellCodice.setCellValue(new HSSFRichTextString("Codice"));
        i++;
        for(Libro l:libri){
            HSSFRow riga=firstSheet.createRow(i);
            HSSFCell cellaAutore=riga.createCell(0);
            cellaAutore.setCellValue(new HSSFRichTextString(l.getAutore()));
            HSSFCell cellaTitolo=riga.createCell(1);
            cellaTitolo.setCellValue(new HSSFRichTextString(l.getTitolo()));
            HSSFCell cellaPrezzo=riga.createCell(2);
            cellaPrezzo.setCellValue(new HSSFRichTextString(formattaDouble(l.getPrezzo())));
            HSSFCell cellaCodice=riga.createCell(3);
            cellaCodice.setCellValue(new HSSFRichTextString(l.getCodice()));
            i++;
           
        }
       
        return workbook;
    }
    private String formattaDouble(double d){
        NumberFormat nf=NumberFormat.getCurrencyInstance(Locale.ITALY);
        nf.setCurrency(Currency.getInstance(Locale.ITALY));
        return nf.format(d);
    }

Java trovare il mime-type di un file

Una funzioncina per tirare fuori il mime-type di un file:


private String getMimeType(File file) {

        MimetypesFileTypeMap mime = new MimetypesFileTypeMap();
       
        return mime.getContentType(file);

    }

venerdì 2 dicembre 2011

Struts errore Module 'null' not found

Se capita un errore di questo tipo nel deploy di una Web App con Struts 1 il problema è dovuto al mancato caricamento della ActionServlet allo start up.
Bisogna ricordarsi di inserire nel web.xml il parametro load-on-startup.
Questo perchè di specifica la servlet è garantito che sia caricata prima della prima chiamata esplicita, se accediamo allo start up di una applicazione struts non è detto quindi che la servlet sia stata già richiamata.

Nel web.xml avremo quindi

<servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
    <param-name>config</param-name>
    <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>

giovedì 1 dicembre 2011

Messaggio di errore "Ant unable to locate tools.jar"

Capita a volte dopo aver installato Ant su Windows di incappare in questo errore.
Ant cerca il jar tools.jar dentro la jre e non dentro la jdk (magari c'è nel path qualche link che fa caricare nel classpath la jre come versione di Java.
Il modo corretto per far funzionare ant su Windows è il seguente:
1) Settare la variabile di ambiente JAVA_HOME(senza bin);
2) Settare la variabile di ambiente ANT_HOME (senza bin);
3) Inserire nella variabile di ambiente PATH, all'inizio in modo da essere sicuri che siano i primi valori caricati nel classpath, i valori %JAVA_HOME%\bin;%ANT_HOME%\bin.

Per verificare la correttezza dell'installazione da DOS digitare ant -version
Se tutto è andato per il verso giusto comparirà un messaggio del tipo

Apache Ant(TM) version 1.8.2 compiled on December 20 2010