printing pages of dynamic height

  • Thread starter Tarlika Elisabeth Schmitz
  • Start date
T

Tarlika Elisabeth Schmitz

Hello,
I must admit I have no experience of java printing other than via
JasperReports and I'd much appreciate a nudge in the right direction.

I need to write to a thermal receipt printer. The length of the
print-out is determined by the number of items sold. The receipt consist
of a [centered] header, one line per item and a total. At the end of the
print-job the printer automatically cuts the paper.

By the looks of it, JasperReports operates with a fixed page length, so
that's that option out of the window.

Can anyone advise how to go about this?

--


Regards/Gruß,

Tarlika Elisabeth Schmitz
 
T

Thomas Weidenfeller

Tarlika said:
Can anyone advise how to go about this?

If you can, use another language. Seriously. Printing support in Java is
rather bad. Java got three (or four? I lost count) printing APIs, all
not too great.

If you receipt printer is not attached to your computer via an interface
known to your particular OS/VM combination for printing, you are almost
completely out of luck. In such a case you would have to implement
printer access via JNI first.

If your VM can talk to the printer, your best bet is the javax.print
API. If you are lucky, your OS/VM/printer combination will provide you
with a reasonable doc flavor. If you are less lucky, you will only get
the doc flavor for preformated data. In the later case you need the
printer's specification to implement the formating manually.

/Thomas
 
T

Tarlika Elisabeth Schmitz

Hello Thomas,

I remember us discussing the sad state of Java print affairs last year.

Thomas said:
If you can, use another language. Seriously. Printing support in Java is
rather bad. Java got three (or four? I lost count) printing APIs, all
not too great.

Not an option. The program is in Java.
If you receipt printer is not attached to your computer via an interface
known to your particular OS/VM combination for printing, you are almost
completely out of luck. In such a case you would have to implement
printer access via JNI first.

However, it will only run on one platform - Debian Linux, CUPS for
printing. (The printer is a thermal USB printer but I suppose that
doesn't matter here.) I don't need a print dialog, it's the default
printer. I just want to print a few damned lines.

But they need some rudimentary formatting:

The Loch Side Café
You were served by Fiona

Leek & Tattie Soup * 2 £5.90
Haggis & Neeps £6.95
Shepherds Pie £7.50

Total £21.95

Needless to say, the amounts need to be right-adjusted. The header maybe
centered.

I found a Java Print Service API CUPS
http://sourceforge.net/projects/jipsi/. Don't know yet whether that is
what I need. Jipsi deals with the printing side, not with the formatting
of the page. AFAIU you just need to create a SimpleDoc from a stream and
start the job.

I'm sorry, I normally try to be a little more clued up before posting a
question but at the moment I don't know where to look. I am not even
sure whether PrintStream is the way forward or whether I need to design
each receipt as a page.

Thanks for your help.

--


Regards/Gruß,

Tarlika Elisabeth Schmitz
 
T

Thomas Weidenfeller

Tarlika said:
However, it will only run on one platform - Debian Linux, CUPS for
printing. (The printer is a thermal USB printer but I suppose that
doesn't matter here.) I don't need a print dialog, it's the default
printer.

If you want to circumvent the whole Java printing system, do what has
been done for at least 30 years in Unix applications for printing: Pipe
your document to the line printer spooler lp or lpr (depends on the Unix
version). In Java you can do it with Runtime.exec().
I just want to print a few damned lines.

But they need some rudimentary formatting:

If you do it manually you need to know the printer specification. Get
the printer manual to understand the printer's language. Or, if
ghostscripts supports this printer, you have to generate PostScript and
of course have ghostscript installed as a printer filter in the printing
system.
I found a Java Print Service API CUPS
http://sourceforge.net/projects/jipsi/. Don't know yet whether that is
what I need.

Only if you need all the CUPS features. If not, your VM should be able
to talk to the classic printing system interface, so you should be able
to get a default PrintService via the javax.print service API.
I'm sorry, I normally try to be a little more clued up before posting a
question but at the moment I don't know where to look.

http://java.sun.com/j2se/1.5.0/docs/guide/jps/

for the latest in Java printing API mess.

/Thomas
 
T

Tarlika Elisabeth Schmitz

Hello Thomas,

Two days and (two nights) down the line ... you drew a bleak picture and
by gaw, it is bleak.

I have designed the till receipts with JasperReports - the prettiest
receipts you've ever seen ;-). I have used JasperReports before on
Windoze and Linux, which had been no problem apart from a few minor
niggles on Linux.

The difference now is that I am not dealing with fixed paper sizes. I
managed to adjust the page height before filling the report. The output
has the correct paper size. But now come the Java printing woes...

Jasper can either
- print (via /java.awt.print.Printable/)
- export to PDF

I really "just" need to print to default printer. Even though the
printer is configured to "variable length" and "Custom paper size",
Jasper/Java print will *always* produce a 11in long receipt. (As though
the page size always defaults to Letter). I have looked through the
Jasper code and am certain that they set the /Page/ height to what I set
it for the document.

The Jasper viewer shows the page in the correct size, PDF output is
correct too. It must fail somewhere between Java and Linux. I also know
that the printer is capapble of dynamic length printing. You can pipe
something to lpr and it will cut at end of doc.

As printing via Jasper, i.e. AWT Print API fails, I tried other routes
via export to PDF.

a) as a Stream into Jipsi (for CUPS), which is based on javax print API.
Same problem - 11in receipt.
b) via javax Print API: lookupDefaultPrintService() (which fails BTW if
you have multiple printers, known bug), SimpleDoc from Stream. Again,
11in receipt. MediaPrintableArea is not IPP conformant and is ignored.

I played around on shell-level:

1) lpr ... receipt.pdf --> 11in page

2) convert receipt.pdf to postscript:
lpr ... receipt.ps produces short receipt. The length information must
be derived from the postscript file (bounding box). Although the length
info must be in the pdf, too, because that's where the .ps came from,
but lpr seems to ignore that.

It seems I have to go down the command line option:

Thomas said:
Tarlika Elisabeth Schmitz wrote:

If you want to circumvent the whole Java printing system, do what has
been done for at least 30 years in Unix applications for printing: Pipe
your document to the line printer spooler lp or lpr (depends on the Unix
version). In Java you can do it with Runtime.exec().

On cmdline level I need to convert PDF to PS and pipe that into lpr.
Sorry, now come the daft questions:
How exactly do I do this? Do I have to write the PDF to disk first?
If you do it manually you need to know the printer specification. Get
the printer manual to understand the printer's language. Or, if

The printer specs are scant - *very* scant. The docs don't give any
examples what command line parameters need to be passed to lpr for
variable length.
We're lucky that we got the docs at all, they'd forgotten to include
them with this version of the driver.


--


Regards/Gruß,

Tarlika Elisabeth Schmitz
 
T

Tarlika Elisabeth Schmitz

Tarlika said:
On cmdline level I need to convert PDF to PS and pipe that into lpr.
Sorry, now come the daft questions:
How exactly do I do this? Do I have to write the PDF to disk first?

Runtime runtime = Runtime.getRuntime();
try
{
/* create named pipe */
String PIPE = System.getProperty("user.home") + '/' + "printStream";
runtime.exec("mkfifo " + PIPE);
FileOutputStream output = new FileOutputStream(PIPE);

/* print with lpr */
String cmd = "lpr -P " + (service.getName())
+ options + '<' + PIPE;
Runtime.getRuntime().exec(new String[] {"/bin/sh","-c",cmd});

/* write document to pipe */
/* AFTER executing lpr or we'll have a deadlock!! */
output.write(printData);
output.close();
deletePipe();
}
catch (Exception e)
{
deletePipe();
}


--


Regards/Gruß,

Tarlika Elisabeth Schmitz
 
T

Tarlika Elisabeth Schmitz

Tarlika said:
Runtime runtime = Runtime.getRuntime();
try
{
/* create named pipe */
String PIPE = System.getProperty("user.home") + '/' + "printStream";

Much simpler ...

Process process = Runtime.getRuntime().exec(printCommand());
OutputStream out = process.getOutputStream();
out.write(printData);
out.close();


This creates a runtime process which executes lpr parameterized with the
document's page size.
lpr will wait until the print date are written to its input stream
(which is our OutputStream).It completes the print job once its input
stream is closed.


--


Regards/Gruß,

Tarlika Elisabeth Schmitz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,186
Messages
2,570,997
Members
47,586
Latest member
Gilda57E93

Latest Threads

Top