Unable to get default printer name while using applet - ZK Framework - java

I want to print my file directly from webpage. For that I am using following reference and trying to implement same with ZUL and Composer.
http://tonny-bruckers.blogspot.in/2012/11/printing-files-directly-from-web-page.html
ZUL File :-
<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 is present inside "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 Class :-
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);
}
}
}
I am able to invoke PrintApplet with this approach but getting Null as service. PrintApplet is working fine with AppletViewer and with normal Java Application but unable to get default printer service while using the above approach.

First I want to mention that APPLET IS ALWAYS RUN ON CLIENT SIDE and APPLET only communicates to the server which from it is downloaded.
That’s why we have to specify codebase directory, so that we can download the applet on client browser by then JAVA Platform Environment plugin from browser takes on control, which in turn run on client JRE environment.
So we have to be very carefully that JDK environment is installed properly.
To trace applet log we can use of java applet console tool ‘jconsole’.
Steps for APPLET to run properly on client browser :
At browser (firefox,chrome,opera) check whether JAVA Platform plugin is there or not, because to run applet from the browser we require that plugin installed and enabled.
If you are working on linux machine: than it is bit complex,
You can find how to enable plugin for LINUX-BROWSER from here:
http://www.oracle.com/technetwork/java/javase/manual-plugin-install-linux-136395.html
Enable console log for applet, when it executes on client JRE, we can look into it for tracing.
Path : JDK_DIR/bin/jcontrol
[JControl Window][1]
For only development purpose: you can lower the security
We have to clear the cache of applet, every time we build new applet, to reflect the latest change we need to clear the cache first, otherwise it'll load cached applet class.
To clear we can use 'javaws -viewer'
Path : JAVA_HOME/bin/javaws -viewer
[Clear Applet Cache][2]
As per your code, your server side code (zul and composer) are perfect but the problem is at applet code.
You are looking for a default printer in print() method, which are one time configuration codes. It has to be in 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));
}
}
And you need another implementation of AccessController to give access to the default printer locate and print.
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(str,PrintService)
Where str can be file name if you want file to be print, or byte array string.
Here in my example, I expected byte array, so I create pdf file from byte array given by the applet from the composer and then it'll sent to the default printer to the given PrintService.
So Actual flow for applet in zk to get access for default printer and to print is by this [graph][3].

Related

How do i screenshot chrome browser when my tests fail and before the chrome browser closes (#After)

I have ran this code and the screenshot gets captured after the chrome browser closes (#After)
If i comment out CloseBrowser(); the screenshot gets captured but the chromebrowser stay open.
I want the screenshot to capture on a failed test then close the browser.
in summary
The screenshot currently captures after the browser closes, which is just a blank .png
I want the screenshot to capture when a test fails just before the browser closes
Thanks
public class TestClass extends classHelper//has BrowserSetup(); and CloseBrowser(); {
#Rule
public ScreenshotTestRule my = new ScreenshotTestRule();
#Before
public void BeforeTest()
{
BrowserSetup();// launches chromedriver browser
}
#Test
public void ViewAssetPage()
{
//My test code here//And want to take screenshot on failure
}
#After
public void AfterTest() throws InterruptedException
{
CloseBrowser();//closes the browser after test passes or fails
}
}
class ScreenshotTestRule implements MethodRule {
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
} catch (Throwable t) {
captureScreenshot(frameworkMethod.getName());
throw t; // rethrow to allow the failure to be reported to JUnit
}
}
public void captureScreenshot(String fileName) {
try {
new File("target/surefire-reports/").mkdirs(); // Insure directory is there
FileOutputStream out = new FileOutputStream("target/surefire-reports/screenshot-" + fileName + ".png");
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
out.close();
} catch (Exception e) {
// No need to crash the tests if the screenshot fails
}
}
};
}
}
You can implement TestNG Listeners to execute code before a test or after a test
Or when a test fails or succeeded etc.
Implement it like below and put your screenshot in the method i showed
public class Listeners implements ITestListener {
Methods…
And put the screenshot code inside the method below:
#Override
public void onTestFailure(ITestResult result) {
code for screenshot
}
}
So i have found a way to implement the screenshots. I have created a method that will take a screenshot. I have put a try and catch around my test code and catch an exception and calling the method to take a screenshot.
public class TestClass extends classHelper//has BrowserSetup(); and CloseBrowser(); {`
#Rule
public ScreenshotTestRule my = new ScreenshotTestRule();
#Before
public void BeforeTest()
{
BrowserSetup();// launches chromedriver browser
}
#Test
public void ViewAssetPage()
{
try
{
//My test code here//And want to take screenshot on failure
}
catch(Exception e)
{
//print e
takeScreenShot();
}
}
#After
public void AfterTest() throws InterruptedException
{
CloseBrowser();//closes the browser after test passes or fails
}
}
///////////////////////////////////////////
void takeScreenShot()
{
try
{
int num = 0;
String fileName = "SS"+NAME.getMethodName()+".png";//name of file/s you wish to create
String dir = "src/test/screenshot";//directory where screenshots live
new File(dir).mkdirs();//makes new directory if does not exist
File myFile = new File(dir,fileName);//creates file in a directory n specified name
while (myFile.exists())//if file name exists increment name with +1
{
fileName = "SS"+NAME.getMethodName()+(num++)+".png";
myFile = new File(dir,fileName);
}
FileOutputStream out = new FileOutputStream(myFile);//creates an output for the created file
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));//Takes screenshot and writes the screenshot data to the created file
//FileOutputStream out = new FileOutputStream("target/surefire-reports/" + fileName);
out.close();//closes the outputstream for the file
}
catch (Exception e)
{
// No need to crash the tests if the screenshot fails
}
This might help:
https://github.com/junit-team/junit4/issues/383
The ordering for rule execution has changed with new 'TestRule'

Vaadin Upload component how get fileName before submitUpload?

I try make implementation for comparing the files before they are uploaded.
If file whith name is exist in system ask about create new version or just override it.
Here is the problem, how to get file name?
I can't use receiveUpload(), because after this method file is remove from upload component ?
The problem is that once you start an upload using the Upload component, it can only be interrupted by calling the interruptUpload() method, and you cannot resume anytime later.
The interruption is permanent.
This means you cannot pause in the middle of the upload to see if you already have the file in your system. You have to upload the file all the way.
Considering this drawback, you can sill check in your system if you have the file, after the upload finishes. If you have the file, you can show a confirmation dialog in which you decide wether to keep the file or overwrite.
The following is an example in which I check in the "system" (I just keep a String list with the filenames) if the file has already been uploaded:
public class RestrictingUpload extends Upload implements Upload.SucceededListener, Upload.Receiver {
private List<String> uploadedFilenames;
private ByteArrayOutputStream latestUploadedOutputStream;
public RestrictingUpload() {
setCaption("Upload");
setButtonCaption("Upload file");
addSucceededListener(this);
setReceiver(this);
uploadedFilenames = new ArrayList<String>();
}
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
latestUploadedOutputStream = new ByteArrayOutputStream();
return latestUploadedOutputStream;
}
#Override
public void uploadSucceeded(SucceededEvent event) {
if (fileExistsInSystem(event.getFilename())) {
confirmOverwrite(event.getFilename());
} else {
uploadedFilenames.add(event.getFilename());
}
}
private void confirmOverwrite(final String filename) {
ConfirmDialog confirmDialog = new ConfirmDialog();
String message = String.format("The file %s already exists in the system. Overwrite?", filename);
confirmDialog.show(getUI(), "Overwrite?", message, "Overwrite", "Cancel", new ConfirmDialog.Listener() {
#Override
public void onClose(ConfirmDialog dialog) {
if (dialog.isConfirmed()) {
copyFileToSystem(filename);
}
}
});
}
private void copyFileToSystem(String filename) {
try {
IOUtils.write(latestUploadedOutputStream.toByteArray(), new FileOutputStream(filename));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
}
private boolean fileExistsInSystem(String filename) {
return uploadedFilenames.contains(filename);
}
}
Note that I have used 2 external libraries:
Apache Commons IO 2.4 (http://mvnrepository.com/artifact/commons-io/commons-io/2.4) for writing to streams
ConfirmDialog from Vaadin Directory (https://vaadin.com/directory#addon/confirmdialog)
You can get the code snippet for this class from Gist: https://gist.github.com/gabrielruiu/9960772 which you can paste into your UI and test it out.

Alfresco action: create a folder with a name from the uploaded metadata

I want to run an action (with a rule) when a file enters the folder in my alfresco repository. The file needs to be moved to a new folder. The new folder will be named after the metadata property "subject" from the file I uploaded.
I am not able to figure out how to do this. Who got any tips?
(A repository webscript is also an option).
This is how I see it:
import java.util.List;
public class MoveExecuter extends ActionExecuterAbstractBase {
public static final String DESTINATION_FOLDER = "destination-folder";
private FileFolderService fileFolderService;
private NodeService nodeService;
#Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList) {
paramList.add(
new ParameterDefinitionImpl(DESTINATION_FOLDER,
DataTypeDefinition.NODE_REF,
true,
getParamDisplayLabel(METADATA VALUE FROM FIELD SUBJECT FROM INCOMING FILE)));}
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) {
NodeRef destinationParent = (NodeRef)ruleAction.getParameterValue(DESTINATION_FOLDER);
// if the node exists
if (this.nodeService.exists(destinationParent) == true) {
try {
fileFolderService.move(incomingfile, destinationParent, null);
} catch (FileNotFoundException e) {
// Do nothing
}
if (this.nodeService.exists(destinationParent) == false) {
try {
nodeService.createNode(parentRef, assocTypeQName, assocQName, "metadata field subject");
fileFolderService.move(incomingfile, destinationParent, null);
} catch (FileNotFoundException e) {
// Do nothing
}
}
}
}
For such a simple action I'd just use a JavaScript instead of a java Action.
Install the JavaScript addon from googlecode or github (newer version)
And just write your Javascript code according the api and run it in runtime in the console to test your code.

How to access the status of the printer?

I need to know the Printer Status. I need to control the Printer Status using Java Program.
Example
Check the Printer status, weather will it accept the Job or not,
Out of Paper
Printer queue
Toner
and etc..
I know there is a way to check the basic information, such as name, color supported or not. But I can't find any example to check paper, toner, job queue. I like to know if it is possible to using Java API. I found big API for printer function, but they didn't give a simple example how to use it.
Have a look at this PrinterStateReason. And also javax.print.
Getting the complete status of a printer is not possible. Printers have a native driver which is able to request services but because there are so many possible printer functionalities, Java only supports a subset of it.
You can actually offer the user to modify the status by calling
PrinterJob pj = PrinterJob.getPrinterJob();
pj.printDialog()
which shows the native printer dialog.
Despite the information in the javax.print API that it is possible to check the printer state, I was not able to do so for my printer !. (Canon).
Code to check:
import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.PrinterStateReason;
import javax.print.attribute.standard.PrinterStateReasons;
import javax.print.attribute.standard.Severity;
import javax.print.event.*;
import java.awt.*;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.*;
import java.util.Set;
/**
* PrintTest
*/
public class PrintTest implements PrintServiceAttributeListener,PrintJobListener,Doc, Printable, PrintJobAttributeListener {
private static final transient String TEXT = "12345";
public static void main(String[] args) {
PrintTest test = new PrintTest();
test.checkPrinters();
}
public void checkPrinters() {
Thread newThread = new Thread(new Runnable() {
public void run() {
PrintService ps = PrinterJob.getPrinterJob().getPrintService();
DocFlavor[] myFlavors = ps.getSupportedDocFlavors();
ps.addPrintServiceAttributeListener(PrintTest.this);
DocPrintJob docJob = ps.createPrintJob();
docJob.addPrintJobAttributeListener(PrintTest.this, null);
docJob.addPrintJobListener(PrintTest.this);
try {
docJob.print(PrintTest.this,null);
}
catch (PrintException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
} });
newThread.start();
/**
PrintServiceAttributeSet attSet = ps.getAttributes();
PrinterStateReasons psr = ps.getAttribute(PrinterStateReasons.class);
if (psr != null) {
Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
for (PrinterStateReason reason : errors)
System.out.printf(" Reason : %s",reason.getName());
System.out.println();
} */
}
public void attributeUpdate(PrintServiceAttributeEvent psae) {
System.out.println(psae.getAttributes());
}
public void printDataTransferCompleted(PrintJobEvent pje) {
System.out.println("Transfer completed");
}
public void printJobCompleted(PrintJobEvent pje) {
System.out.println("Completed");
}
public void printJobFailed(PrintJobEvent pje) {
System.out.println("Failed");
PrinterStateReasons psr = pje.getPrintJob().getPrintService().getAttribute(PrinterStateReasons.class);
if (psr != null) {
Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
for (PrinterStateReason reason : errors)
System.out.printf(" Reason : %s",reason.getName());
System.out.println();
}
}
public void printJobCanceled(PrintJobEvent pje) {
System.out.println("Canceled");
}
public void printJobNoMoreEvents(PrintJobEvent pje) {
System.out.println("No more events");
}
public void printJobRequiresAttention(PrintJobEvent pje) {
System.out.println("Job requires attention");
PrinterStateReasons psr = pje.getPrintJob().getPrintService().getAttribute(PrinterStateReasons.class);
if (psr != null) {
Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
for (PrinterStateReason reason : errors)
System.out.printf(" Reason : %s",reason.getName());
System.out.println();
}
}
public DocFlavor getDocFlavor() {
return DocFlavor.SERVICE_FORMATTED.PRINTABLE; //To change body of implemented methods use File | Settings | File Templates.
}
public Object getPrintData() throws IOException {
return this;
}
public DocAttributeSet getAttributes() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public Reader getReaderForText() throws IOException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public InputStream getStreamForBytes() throws IOException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
return pageIndex == 0 ? PAGE_EXISTS : NO_SUCH_PAGE; //To change body of implemented methods use File | Settings | File Templates.
}
public void attributeUpdate(PrintJobAttributeEvent pjae) {
System.out.println("Look out");
}
}
I have tried to get a PrinterReasonsState by willfully opening the case or removing the paper, but I was unsuccessfull. Perhaps someone else can show how it is possible, but so far it seems that the API offers much more functionality which is in reality not available.
Or in short:
It does not work, at least not for my printer.
I was told one could check the printer status this way:
PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
AttributeSet attributes = printService.getAttributes();
String printerState = attributes.get(PrinterState.class).toString();
String printerStateReason = attributes.get(PrinterStateReason.class).toString();
System.out.println("printerState = " + printerState); // May be IDLE, PROCESSING, STOPPED or UNKNOWN
System.out.println("printerStateReason = " + printerStateReason); // If your printer state returns STOPPED, for example, you can identify the reason
if (printerState.equals(PrinterState.STOPPED.toString()) {
if (printerStateReason.equals(PrinterStateReason.TONER_LOW.toString()) {
System.out.println("Toner level is low.");
}
}
Sadly it seems that my printer doesn't have support for printerState so I can't test it.
UPDATE:
Instead of querying WMI "win32_printer" object I would recommend using Powershell directly like this, its much cleaner API :
Get-Printer | where PrinterStatus -like 'Normal' | fl
To see all the printers and statuses:
Get-Printer | fl Name, PrinterStatus
To see all the attributes:
Get-Printer | fl
You can still use ProcessBuilder in Java as described below.
Before update:
Solution for Windows only.
In Windows you can query WMI "win32_printer" class, so you check that the state on OS layer: Win32_Printer class
In Java you can use ProcessBuilder like this to start PowerShell and execute the PS script like this:
String printerName = "POS_PRINTER";
ProcessBuilder builder = new ProcessBuilder("powershell.exe", "get-wmiobject -class win32_printer | Select-Object Name, PrinterState, PrinterStatus | where {$_.Name -eq '"+printerName+"'}");
String fullStatus = null;
Process reg;
builder.redirectErrorStream(true);
try {
reg = builder.start();
fullStatus = getStringFromInputStream(reg.getInputStream());
reg.destroy();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.print(fullStatus);
After converting the InputStream to String you should get something like that:
Name PrinterState PrinterStatus
---- ------------ -------------
POS_PRINTER 0 3
State and Status should change for various situations (printer turned off, out of paper, cover opened,...).
This should work, but depends on the printer and drivers. I used this with EPSON TM printers with ESDPRT port and I could get information like: no paper, cover open, printer offline/turned off, printer paused.
More comprehensive answer here:
- my StackOverflow answer on a similar question.

printing to a networked printer using java

i require to send a pdf document to print on the server side of a web app, the printer fully supports pdf printing etc, it is networked as well to the server. The pdf is also stored on the server.
what i am trying to is on a button click, print out the pdf file, currently i have the code below :
//Server side printing
public class PrintDocument {
public void printText(String text) throws PrintException, IOException {
//Looks for all printers
//PrintService[] printServices = PrinterJob.lookupPrintServices();
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
InputStream is = new ByteArrayInputStream(text.getBytes("UTF8"));
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(new Copies(1));
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
Doc doc = new SimpleDoc(is, flavor, null);
DocPrintJob job = service.createPrintJob();
PrintJobWatcher pjw = new PrintJobWatcher(job);
job.print(doc, pras);
pjw.waitForDone();
is.close();
}
}
class PrintJobWatcher {
boolean done = false;
PrintJobWatcher(DocPrintJob 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;
System.out.println("Printing has successfully completed, please collect your prints)");
PrintJobWatcher.this.notify();
}
}
});
}
public synchronized void waitForDone() {
try {
while (!done) {
wait();
}
} catch (InterruptedException e) {
}
}
}
But i have a few questions / issues, how do i put the pdf into the input stream for this to be printed out, can i select options such as duplex printing, and how can i call this from inside a JSF web app
Thanks
According to this article it should be possible to start a print job with a PJL block (Wikipedia link includes pointers to the PJL reference documentation), followed by the PDF data.
Thank to PJL you should be able to control all features the printer has to offer including duplex, etc - the blog article even mentions stapling of a combined printout of 2 pdfs.
Be sure to read the comments on the article as well, there is a comment from the guy who's listed as inventor on the patent as well with extra information on the PJL commands.
Take a look at this blog. We had to print documents with duplex print option.
Its not possible to duplex print directly in java. However the work around is to use ghostscript and convert PDF to PS (Post script file). To that you can add either PJL Commands or Post script commands.
More info at
http://reddymails.blogspot.com/2014/07/how-to-print-documents-using-java-how.html
Also read similar question
Printing with Attributes(Tray Control, Duplex, etc...) using javax.print library
After reading through this Q&A I spent awhile working with the javax.print library only to discover that it is not very consistent with printer option support. I.e. even if a printer has an option like stapling, the javax.printer library showed it as "stapling not supported".
So I then tried out PJL commands using a plain java socket and it worked great, in my tests it also printed faster than the javax.print library, it has a much smaller code footprint and best part is no libraries are needed at all:
private static void print(File document, String printerIpAddress)
{
try (Socket socket = new Socket(printerIpAddress, 9100))
{
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String title = document.getName();
byte[] bytes = Files.readAllBytes(document.toPath());
out.write(27);
out.write("%-12345X#PJL\n".getBytes());
out.write(("#PJL SET JOBNAME=" + title + "\n").getBytes());
out.write("#PJL SET DUPLEX=ON\n".getBytes());
out.write("#PJL SET STAPLEOPTION=ONE\n".getBytes());
out.write("#PJL ENTER LANGUAGE=PDF\n".getBytes());
out.write(bytes);
out.write(27);
out.write("%-12345X".getBytes());
out.flush();
out.close();
}
catch (Exception e)
{
System.out.println(e);
}
}
See this for more info on attempts with javax.print.

Categories

Resources