Невозможно получить имя принтера по умолчанию при использовании апплета - ZK Framework

Я хочу распечатать свой файл прямо с веб-страницы. Для этого я использую следующую ссылку и пытаюсь реализовать то же самое с ZUL и Composer.

http://tonny-bruckers.blogspot.in/2012/11/printing-files-directly-from-web-page.html

Файл ZUL:-

<zk>
<applet code = "PrintApplet.class" codebase = "applet/" id="printApplet" width="400px" style="border: 1px" />
<button id="btnClickMe" label="Click Me" sclass="light-btn"/>
</zk>

PrintApplet.class присутствует внутри "WebContent/applet".

public class AppletComposer extends GenericForwardComposer<Window> {
    private Applet printApplet;
    public void doOverrideAfterComposer(Window comp) throws Exception {

    }
    public void onClick$btnClickMe(Event event) throws Exception {
        String Originalstr = "ByteArrayInputStream Example!";
        byte[] Originalbytes = Originalstr.getBytes();
        ByteArrayInputStream bis=new ByteArrayInputStream(Originalbytes);
        printApplet.invoke("print", bis);
    }
}

Класс PrintApplet:-

public class PrintApplet extends Applet {
    public void init() 
    {

    }
    public void print(ByteArrayInputStream bis) throws PrintException 
    {
        PrintService service = PrintServiceLookup.lookupDefaultPrintService();
        if (service != null) {
            DocFlavor psFormat = DocFlavor.INPUT_STREAM.PDF;
            PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();    
            DocPrintJob job = service.createPrintJob();
            Doc pdfDoc = new SimpleDoc(bis,psFormat, null);
            job.print(pdfDoc, attributes);         
        }
    }
}

Я могу вызвать PrintApplet с таким подходом, но получить Null в качестве службы. PrintApplet работает нормально с AppletViewer и с обычным Java-приложением, но не может получить службу принтера по умолчанию при использовании вышеуказанного подхода.

1 ответ

Решение

Прежде всего я хочу отметить, что APPLET ВСЕГДА РАБОТАЕТ НА СТОРОНЕ КЛИЕНТА, и APPLET связывается только с сервером, который с него загружается.

Вот почему мы должны указать каталог codebase, чтобы мы могли загрузить апплет в клиентском браузере, а затем подключить плагин JAVA Platform Environment из браузера, который, в свою очередь, запускается в клиентской среде JRE.

Поэтому мы должны быть очень осторожны, чтобы среда JDK была установлена ​​правильно. Для отслеживания журнала апплета мы можем использовать консольный инструмент Java-апплета 'jconsole'.


Шаги для правильной работы APPLET в браузере клиента:

  1. В браузере (Firefox, Chrome, Opera) проверьте, есть ли плагин JAVA Platform или нет, потому что для запуска апплета из браузера нам требуется, чтобы плагин был установлен и включен.

    Если вы работаете на машине с Linux: чем она немного сложнее, вы можете узнать, как включить плагин для LINUX-BROWSER здесь:

    http://www.oracle.com/technetwork/java/javase/manual-plugin-install-linux-136395.html

  2. Включите консольный журнал для апплета, когда он выполняется на клиентском JRE, мы можем посмотреть его для отслеживания.

    Путь: JDK_DIR / bin / jcontrol

    [Окно JControl][1]

    Только для целей разработки: вы можете снизить безопасность

  3. Мы должны очищать кэш апплета каждый раз, когда мы создаем новый апплет, чтобы отразить последние изменения, нам нужно сначала очистить кеш, иначе он загрузит кэшированный класс апплета.

    Чтобы очистить, мы можем использовать 'javaws -viewer'

    Путь: JAVA_HOME / bin / javaws -viewer

    [Очистить кэш апплета][2]


Согласно вашему коду, ваш серверный код (zul и composer) идеален, но проблема в коде апплета.

Вы ищете принтер по умолчанию в методе print(), который является однократным кодом конфигурации. Это должно быть в init ().

PrintApplet.java

public class PrintApplet extends Applet {

 private static final long serialVersionUID = 1L;
 private PrintService service;

 public void init() 
 {
    JOptionPane.showMessageDialog(null, "Inside INIT()");
    if(null==service){
        service = PrintServiceLookup.lookupDefaultPrintService();
        System.out.println(service.getName());
    } else {
        System.out.println(service.getName());
    }
 }
 public void print(String str) throws PrintException 
 {
    JOptionPane.showMessageDialog(null, "Inside print()");
    JOptionPane.showMessageDialog(null, "String is:::"+str);
    cPrint cP = new cPrint(str, service);
    System.out.println((Integer) AccessController.doPrivileged(cP));
 }
}

И вам нужна другая реализация AccessController для предоставления доступа к расположению и печати принтера по умолчанию.

cPrint.java

class cPrint implements PrivilegedAction<Object> {
 String str;
 PrintService service;

 public cPrint(String str, PrintService argPrintService) {

    this.str = str;
    this.service = argPrintService;

 };
 public Object run() {
    // privileged code goes here
    InputStream is = null;
    try 
    {
        JOptionPane.showMessageDialog(null, "String is:::"+str);
        byte[] Originalbytes = str.getBytes();
        JOptionPane.showMessageDialog(null, "Original bytes:::"+Originalbytes);
        is=new ByteArrayInputStream(Originalbytes);
        FileWriter fstream = new FileWriter("/home/test/out.pdf");  
        BufferedWriter out = new BufferedWriter(fstream);  
        for (Byte b: Originalbytes) {  
            out.write(b);  
        }  
        out.close();
        DocPrintJob printJob = service.createPrintJob();
        Doc doc;
        DocAttributeSet docAttrSet = new HashDocAttributeSet();
        PrintRequestAttributeSet printReqAttr = new HashPrintRequestAttributeSet();
        doc = new SimpleDoc(is, DocFlavor.INPUT_STREAM.AUTOSENSE, docAttrSet);
        PrintJobWatcher pjDone = new PrintJobWatcher(printJob);
        printJob.print(doc, printReqAttr);
        pjDone.waitForDone();
        // It is now safe to close the input stream
        is.close();
     } 
     catch (Exception e) {
        e.printStackTrace();
        System.out.println(e);
        return 1;
     } 
    return 0;
  }
  static class PrintJobWatcher {
    // true iff it is safe to close the print job's input stream
    boolean done = false;

    PrintJobWatcher(DocPrintJob job) {
        // Add a listener to the print job
        job.addPrintJobListener(new PrintJobAdapter() {
            public void printJobCanceled(PrintJobEvent pje) {
                allDone();
            }
            public void printJobCompleted(PrintJobEvent pje) {
                allDone();
            }
            public void printJobFailed(PrintJobEvent pje) {
                allDone();
            }
            public void printJobNoMoreEvents(PrintJobEvent pje) {
                allDone();
            }
            void allDone() {
                synchronized (PrintJobWatcher.this) {
                    done = true;
                    PrintJobWatcher.this.notify();
                }
            }
        });
    }
    public synchronized void waitForDone() {
        try {
            while (!done) {
                wait();
            }
        } catch (InterruptedException e) {
        }
    }
 }
}

cPrint (ул,PrintService)

Где str может быть именем файла, если вы хотите, чтобы файл печатался, или строкой байтового массива.

Здесь, в моем примере, я ожидал байтовый массив, поэтому я создаю pdf-файл из байтового массива, предоставленного апплетом от композитора, и затем он отправляется на принтер по умолчанию для данного PrintService.

Таким образом, фактический поток для апплета в zk, чтобы получить доступ к принтеру по умолчанию и распечатать, - это [graph][3].

Другие вопросы по тегам