Print to local printer from webui

2,067 views
Skip to first unread message

Jan Thielemann

unread,
Jun 17, 2013, 4:19:39 AM6/17/13
to idem...@googlegroups.com
Hello everyone,
i've created a dashboard panel which shows me my recently created invoices. I now want to select a bunch of these and print them. To do this, i use the following code:

MProcess process = MProcess.get(Env.getCtx(),MProcess.getProcess_ID("JasperInvoice", null));
MPInstance pInstance = new MPInstance(process, c_invoice_id);
ProcessInfo pi = new ProcessInfo("", process.getAD_Process_ID());
pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID());
pi.setRecord_ID(c_invoice_id);
pi.setTitle(title);
pi.setIsBatch(false);
pi.setTable_ID(MInvoice.Table_ID);
ReportStarter starter = new ReportStarter();
processOK = starter.startProcess(Env.getCtx(), pi, null);

Now the problem:
The dashboard panel is run inside the server which is itself located on some remote machine. If i generate a pdf from the jasper report i can print it manually to any local printer from within the pdf previewer. If i try to print it directly with the code above, i get a nullpointerexception. I think this is due to the fact that the server machine doesn't know any printer because if i run the server on my local maschine, it finds the local default printer and prints it. Is there a way that i can print something directly on the default printer but not on the servers default printer but the clients one?

I hope you understand my problem and can help me.

Heng Sin Low

unread,
Jun 17, 2013, 4:32:59 AM6/17/13
to idem...@googlegroups.com
Html5 doesn't offer api to print direct to your printer so can't do this with just zk and javascript code. One way around this is to use java appet - create an invisible java applet to fetch the generated pdf from server and print it to the default client printer.


--
You received this message because you are subscribed to the Google Groups "iDempiere" group.
To unsubscribe from this group and stop receiving emails from it, send an email to idempiere+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ken Longnan

unread,
Jun 17, 2013, 9:54:16 AM6/17/13
to idempiere

As i know Chrome has supported view pdf directly in web, but i am not sure any script can operate with chrome pdf viewer for local printing.

armenrz

unread,
Jun 18, 2013, 2:53:36 AM6/18/13
to idem...@googlegroups.com
Hi Jan,

I'm also interested in seeking similar solution. I recently need Invoice Print process to be able to do "silent printing".

Regards,

Armen

Jan Thielemann

unread,
Jun 18, 2013, 4:34:08 AM6/18/13
to idem...@googlegroups.com
Is there any reference code i could use to create an applet for zk in java code? I tried this to load my applet from within my dashboard panel but it won't work. Instead, after i log in, the whole dashboard/webui loads forever and doesn't show any content:

org.zkoss.zul.Applet applet = new org.zkoss.zul.Applet();
applet.setCode("MyApplet.class");
layout.appendChild(applet);

The layout is a Vlayout which contains all of my dashboard panel gui. The MyApplet class is just a java.awt.Applet with some sysouts. I've never used applets before so maybe i'm missing something. Hopefully you can help

Heng Sin Low

unread,
Jun 18, 2013, 5:16:57 AM6/18/13
to idem...@googlegroups.com
There's a LabelAppletWindow in the current zk source. The source for labelapplet.jar is missing though, you can try to decompile it if you need it now ( will check in that later today or tomorrow ).


--

Jan Thielemann

unread,
Jun 18, 2013, 6:22:46 AM6/18/13
to idem...@googlegroups.com
Thanks a lot hengsin

Jan Thielemann

unread,
Jun 18, 2013, 8:17:03 AM6/18/13
to idem...@googlegroups.com
I followd your hint hengsin and this is what happend:
-I created myapplet.jar which contains the same things as labelapplet.jar.
-I used the code from LabelAppletWindow to load the applet
-When i log in, i get this typical zk error telling me "Failed to process. script. Cannot set property 'innerHTML' of null (TypeError)

When i debug and take a look at the script string, i get:
document.getElementById('z__i491').innerHTML="<applet code='MyApplet.class' archive='myapplet.jar' width=0 height=0 />";

I wonder what i am doing wrong.

Heng Sin Low

unread,
Jun 18, 2013, 8:20:05 AM6/18/13
to idem...@googlegroups.com
"z__i491" means you get the uuid before it is attached to a page, i.e before setParent or appendChild call. you need to get the uuid  after, not before.


--

Jan Thielemann

unread,
Jun 18, 2013, 8:39:25 AM6/18/13
to idem...@googlegroups.com
This is my code to start the applet. Its the same like you do in LabelAppletWindow.java
private void initApplet(){
Div div = new Div();
layout.appendChild(div);
StringBuffer appletTag = new StringBuffer();
appletTag.append("<applet code='MyApplet.class' width=0 height=0>");
appletTag.append("</applet>");
String script = "document.getElementById('" + div.getUuid() + "').innerHTML=\"" + appletTag.toString() + "\";";
Clients.response(new AuScript(div, script));
}

Jan Thielemann

unread,
Jun 18, 2013, 8:41:37 AM6/18/13
to idem...@googlegroups.com
The fragment.jar looks like this:
root
--META-INF/
----MANIFEST.MF
--org/adempiere/webui/dashboard/
----MyDashboardPanel.class
--zul/
----MyDashboardZul.zul
--MyApplet.class

Heng Sin Low

unread,
Jun 18, 2013, 9:10:37 AM6/18/13
to idem...@googlegroups.com
does layout already have parent when you call div.getUuid() ? There's nothing wrong with your code above, but the uuid you get from div.getUuid() is not going to stay if it is not attached to a page yet.


}

--

Jan Thielemann

unread,
Jun 19, 2013, 7:35:05 AM6/19/13
to idem...@googlegroups.com
Hello hengsin,
i finally managed to get the applet working but now a new problem occurred: the .jsp is telling me that the key is not found but it has the same key (uuid) i generated and handed over to the applet. It seems that the list is not handed over. Any idea whats going wrong?

Jan Thielemann

unread,
Jun 19, 2013, 8:06:25 AM6/19/13
to idem...@googlegroups.com
Maybe it has something to do with the HttpSession. In my dashboard panel (from where i start the applet) the session is for example
org.apache.catalina.session.StandardSessionFacade@486ebc68

but in the jsp it is another one:
org.apache.catalina.session.StandardSessionFacade@3edbb948

Heng Sin Low

unread,
Jun 19, 2013, 8:25:00 AM6/19/13
to idem...@googlegroups.com

If it is from the same domain and application context, it should share the same session. You can try to use the jsessionid approach to ensure that as well.

Jan Thielemann

unread,
Jun 19, 2013, 8:44:38 AM6/19/13
to idem...@googlegroups.com
I use nearly the exact same code as the label printer applet. I only altered the name of the applet as well as the jar. If i didn't change anything else... What do you mean by jsessionid appraoch? 

Heng Sin Low

unread,
Jun 19, 2013, 8:54:12 AM6/19/13
to idem...@googlegroups.com

Jan Thielemann

unread,
Jun 19, 2013, 9:13:19 AM6/19/13
to idem...@googlegroups.com
Sorry but i cannot follow you. I basically use the exact same code for my applet/jsp like you do with label printer. How did you manage to get the right session? Do i have to configure something? Here are the code i use for creating the applet, the applet itself and the jsp:

private void printPDFWithApplet(List <byte[]> list){
//UUID generieren und das PDF als Attribut in der Sitzung speichern
String uuid = UUID.randomUUID().toString();
HttpSession session = (HttpSession) Executions.getCurrent().getDesktop().getSession().getNativeSession();
session.setAttribute(uuid, list);
System.out.println("Session ist " + session);
//Button zum schließen des Applets
ToolBarButton link = new ToolBarButton();
link.setLabel("Click here to close this popup after printing is completed.");
link.addEventListener(Events.ON_CLICK, this);
appendChild(link);
//Neuer Div für das Applet
Div div = new Div();
appendChild(div);
//Code um das Applet zu starten. Dabei uuid mit übergeben
StringBuffer appletTag = new StringBuffer();
appletTag.append("<applet code='MyApplet.class' archive='myapplet.jar' width=0 height=0>");
appletTag.append("<param name='key' value='" + uuid + "'>");
appletTag.append("<param name='size' value='" + list.size() + "'>");
for(int i = 0; i < list.size(); i++)
appletTag.append("<param name='data_" + i + "' value='" + Base64.encodeBase64(list.get(i)) + "'>");
appletTag.append("</applet>");
String script = "document.getElementById('" + div.getUuid() + "').innerHTML=\"" + appletTag.toString() + "\";";
Clients.response(new AuScript(div, script));
}







--------------------------------------------------------------------------------------------------------------------------------------------------------------------------


import java.awt.print.PrinterJob;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.SimpleDoc;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.standard.DocumentName;
import javax.swing.JApplet;

import org.apache.commons.codec.binary.Base64;





public class MyApplet extends JApplet{
private static final long serialVersionUID = 1L;
 private String key;
 private int listSize = 0;
 private List<byte[]> list;
 
 public void init()
 {
 this.key = getParameter("key");
   String s = getParameter("size");
   try {
     this.listSize = Integer.parseInt(s);
   } catch (Exception e) {
     System.out.println("Invalid listSize param=" + s);
     this.listSize = 0;
   }

   this.list = new ArrayList();
   for (int i = 0; i < this.listSize; i++)
   {
     String data = getParameter("data_" + i);
     this.list.add(Base64.decodeBase64(data));
   }
   
 super.init();
 
 
 showStatus("DAS APPLET IST JETZT INITIALISIERT!!!!!!!!!!!!!!!!!!!!!!!!!!");
 }

 
 public void start()
 {
   System.out.println(getClass().getName() + " start()");
   PrinterJob pjob = null;
   PrintService service = null;
   DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
   try
   {
     int count = 0;
     do
     {
       URL url = new URL(getCodeBase(), "myapplet.jsp?key=" + this.key + "&count=" + (count + 1));

       System.out.println("Protocol=" + url.getProtocol());
       System.out.println("Host=" + url.getHost());
       System.out.println("Port=" + url.getPort());
       System.out.println("Default Port=" + url.getDefaultPort());
       System.out.println("Path=" + url.getPath());
       System.out.println("URL=" + url.toString());

       URLConnection conn = url.openConnection();

       int contentLength = conn.getContentLength();
       System.out.println("ContentLength=" + contentLength);

       InputStream is = conn.getInputStream();
       System.out.println("InputStream=" + is.available());

       byte[] data = (byte[])null;
       if (contentLength != is.available())
       {
         data = (byte[])this.list.get(count);
         System.out.println("list=" + data.length);
       }
       else
       {
         BufferedInputStream bis = new BufferedInputStream(is);
         System.out.println("BufferedInputStream=" + bis.available());

         ByteArrayOutputStream baos = new ByteArrayOutputStream(contentLength);
         while (bis.available() > 0) {
           baos.write(bis.read());
         }
         is.close();
         bis.close();

         data = baos.toByteArray();
         baos.close();
         System.out.println("ByteArrayOutputStream=" + data.length);
       }

       if ((data == null) || (data.length <= 0)) break;
       count++;
       if (pjob == null)
       {
         pjob = PrinterJob.getPrinterJob();
         if (!pjob.printDialog()) break;
         service = pjob.getPrintService();
       }

       DocPrintJob job = service.createPrintJob();
       HashDocAttributeSet as = new HashDocAttributeSet();
       as.add(new DocumentName("shipping label", null));
       Doc doc = new SimpleDoc(data, flavor, as);
       job.print(doc, null);
     }

     while (count < this.listSize);

     showStatus(count + " label printed.");
   } catch (Exception e) {
     e.printStackTrace();
     showStatus("Failed to print label - " + e.getLocalizedMessage());
   }
 }


 public void destroy()
 {
   System.out.println(getClass().getName() + " destroy()");
 }

 public void stop()
 {
   System.out.println(getClass().getName() + " stop()");
 }
}




--------------------------------------------------------------------------------------------------------------------------------------------------------------------------


<%@page import="java.io.BufferedOutputStream"%>
<%@page import="java.io.OutputStream"%>
<%@page import="java.util.Enumeration"%>
<%@page language="java" contentType="application/octet-stream"%>
<%
String key = request.getParameter("key");
if (key == null || key.trim().length() == 0 )
return;
Object object = session.getAttribute(key);
if (object != null && object instanceof java.util.List) {
java.util.List list = (java.util.List)object;
System.out.println("size=" + list.size());
if (!list.isEmpty()) {
byte[] data = (byte[])list.remove(0);
System.out.println("length=" + data.length);
response.setContentLength(data.length);
OutputStream os = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
bos.write(data);
bos.flush();
} else {
response.setContentLength(0);
}
} else {
System.out.println("key not found=" + key);
response.setContentLength(0);
}
%>



I would really appreciate any help. The whole topic is totally new to me :(


Heng Sin Low

unread,
Jun 19, 2013, 9:33:17 AM6/19/13
to idem...@googlegroups.com
Ok, you can try this workaround, pass the session id from zk to the applet using the param tag. In your applet, get the session id parameter and add it to the jsp url, i.e replace myapplet.jsp?... with myapplet.jsp;jsessionid={your session id param}?...



Jan Thielemann

unread,
Jun 20, 2013, 9:25:07 AM6/20/13
to idem...@googlegroups.com
I give up on this topic. I managed to get the applet running but it only worked in firefox and not chrome...

My new approach is to generate a pdf for each invoice in a loop and then merge all the files into one big pdf which i show to the user using the SimplePDFViewer which works well so far

Hesham Ahmed

unread,
Jun 22, 2013, 10:14:51 AM6/22/13
to idem...@googlegroups.com
I managed to get auto printing of PDF with jasper reports and PDF JavaScript. The solution works on all platforms when using Adobe Reader plugin. Chrome/Firefox built-in PDF viewer does not allow silent printing and I couldn't find any option to enable it YMMV. Follow these steps to get silent printing with Adobe Reader browser plugin:

On your jasper report add a property: net.sf.jasperreports.export.pdf.javascript
Set the value to the following script:
var pp = this.getPrintParams(); 
pp.interactive = pp.constants.interactionLevel.silent; 
this.print(pp);

Deploy the report and run it. Upon running it would ask if you want to print? Say yes and it would print. To get rid of the print pop-up add idempiere server to trusted servers on Acrobat Reader
In Adobe Reader preference go to Security (Enhanced) tab
Make sure "Enable Enhanced Security" is checked
Click at add host and the URL to idempiere server (e.g. https://demo.idempiere.com)

Now when you open the report it should auto print to the default printer.

Regards,

Hesham 

Hiep Lq

unread,
Jun 22, 2013, 1:26:01 PM6/22/13
to idem...@googlegroups.com

hi Thielemann.
In liferay framwork. it has a button print for each portlet.
when click print button. a new popup windown display and print dialog for print this popup windown is also display.

no magic in that. flow process is below 
1. when click print button. a request with display mode is print is post to server.
2. server response a page with layout for print.
3. after page loaded. a script is auto run. it only call javascript function windown.print ();

because my english is bad. i can wrong understand your problem. hope it can help you.

Hiep Lq

unread,
Sep 7, 2016, 2:30:19 PM9/7/16
to iDempiere
by now can't use adobe plugin in chrome.
I do extract same you but use standalone adobe reader

https://www.facebook.com/hieplq1604/posts/2076441102581696

by standard report use itext library to create pdf, so solution is same.

Kubavat Hardik

unread,
Feb 14, 2018, 12:43:07 AM2/14/18
to iDempiere
Hi Hiep,

I am looking for silent printing in webui and I landed to this link : http://wiki.idempiere.org/en/Silent_print.

But in this link whatever the changeset links defined it removed I think. Is there any reference available for same?
Reply all
Reply to author
Forward
0 new messages