読者です 読者をやめる 読者になる 読者になる

AJAXDownload ビヘビア、

Wicket

Wicket8 が前提の話だが、ビヘビアをラムダで。。を考え出すと、次から次へと出てくる。。。
AJAX の振る舞いで動かすダウンロード、以前、
Wicket 6.x→7.x でファイルダウンロード時のファイル名の注意 - Oboe吹きプログラマの黙示録
この中で、public abstract class AJAXDownload を書いた。
でもこれは、以下のように、インスタンス生成の staticメソッド-ラムダを用意すれば、
もう少しスッキリする。

import java.io.IOException;
import java.io.OutputStream;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
import org.apache.wicket.request.resource.ContentDisposition;
import org.apache.wicket.util.resource.AbstractResourceStreamWriter;
import org.apache.wicket.util.resource.IResourceStream;
import org.danekja.java.util.function.serializable.SerializableConsumer;
import org.danekja.java.util.function.serializable.SerializableSupplier;
/**
 * AJAX Download.
 */
public abstract class AJAXDownload extends AbstractAjaxBehavior{
   protected abstract IResourceStream getResourceStream();

   public void callBackDownload(AjaxRequestTarget target){
      target.appendJavaScript("setTimeout(\"window.location.href='" + getCallbackUrl().toString() + "'\", 100);");
   }

   @Override
   public void onRequest(){
      try{
      ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(getResourceStream(), getFileName());
         handler.setContentDisposition(ContentDisposition.ATTACHMENT);
         getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
      }catch(Exception e){
         throw new RuntimeException(e.getMessage(), e);
      }
   }
   protected String getFileName(){
      return null;
   }

   public static AJAXDownload of(SerializableConsumer<OutputStream> write
   , SerializableSupplier<String> getConteType, SerializableSupplier<String> getName){
      return new AJAXDownload(){
         @Override
         protected IResourceStream getResourceStream(){
            return new AbstractResourceStreamWriter(){
               @Override
               public void write(OutputStream out) throws IOException{
                  write.accept(out);
                  out.close();
               }
               @Override
               public String getContentType(){
                  return getConteType.get();
               }
            };
         }
         @Override
         protected String getFileName(){
            return getName.get();
         }
      };
   }
}

とすれば、、

final AJAXDownload download = AJAXDownload.of(out->{
   // out への出力
}, ()->"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ()->"foo.xlsx");
compoment.add(download);
queue(AjaxLink.onClick("download", t->{
   // 出力準備の後で、、
   download.callBackDownload(t);
}).add(download));

OutputStream の close の書き忘れを気にしなくてよい。