Il sistema di cache tende infatti a non far lanciare a Wicket la onClick del link con la conseguenza che eventuali variazioni sui dati avvenuti in seguito, per esempio, ad un filtro su una form, non venissero recepiti dalla funzione di creazione PDF che stampava quindi i vecchi risultati.
La soluzione in questione permette di introdurre il concetto di stampa PDF anche da AjaxLink. Questo risolve la problematica di cui sopra perché l'Ajax Link non viene riconosciuto come componente analogo e quindi non entra nella cache.
Per realizzare questo, basta creare la seguente classe:
Usarla è molto semplice.import java.io.InputStream; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.behavior.AbstractAjaxBehavior; import org.apache.wicket.request.Response; import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler; import org.apache.wicket.request.http.WebResponse; import org.apache.wicket.request.resource.ContentDisposition; import org.apache.wicket.util.resource.AbstractResourceStreamWriter; import org.apache.wicket.util.resource.IResourceStream; public class AJAXFileDownload extends AbstractAjaxBehavior { private static final long serialVersionUID = 1L; private boolean addAntiCache; private String fileName; private InputStream is; public AJAXFileDownload() { this(true); } public AJAXFileDownload(boolean addAntiCache) { super(); this.addAntiCache = addAntiCache; } /** * Call this method to initiate the download. */ public void initiate(AjaxRequestTarget target, String fileName, InputStream is) { this.fileName = fileName; this.is = is; String url = getCallbackUrl().toString(); if (addAntiCache) { url = url + (url.contains("?") ? "&" : "?"); url = url + "antiCache=" + System.currentTimeMillis(); } // the timeout is needed to let Wicket release the channel target.appendJavaScript("setTimeout(\"window.location.href='" + url + "'\", 100);"); } public void onRequest() { ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(getResourceStream(), getFileName()); handler.setContentDisposition(ContentDisposition.ATTACHMENT); getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler); } protected String getFileName() { return this.fileName; } /** * Hook method providing the actual resource stream. */ protected IResourceStream getResourceStream() { return new AbstractResourceStreamWriter() { private static final long serialVersionUID = 1L; public void write(Response output) { WebResponse response = (WebResponse)output; byte[] buffer = new byte[256]; try { int read; while((read = is.read(buffer)) != -1) { response.write(buffer, 0, read); response.flush(); } response.close(); } catch (Exception e) { response.write(e.toString().getBytes()); response.close(); } } }; } }
In questo modo potete generare tutti i PDF che volete.//Istazione l'oggetto di cui sopra final AJAXFileDownload fileDownload = new AJAXFileDownload(); AjaxLink printLink = new AjaxLink("stampa"){ public void onClick(AjaxRequestTarget target) { //operazioni per avere il contenuto del PDF final byte[] pdf = creaPDFinQualcheModo(); fileDownload.initiate(target, "nomefile.pdf", new ByteArrayInputStream(pdf)); } }; printLink.add(fileDownload); add(printLink); //aggiungo il link al componente padre