I want to print a PDF file to Zebra printer using a Java application. I have generated a PDF using Jasper reports with 2D bar codes. If I am performing manual print to Zebra printer it's printing that PDF file but once I am trying to print the same pdf file using the Java application, the job is submitting to printer but print is not happening.
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;
public class ZebraPrintUtil {
public static void main(String[] args) throws IOException, InterruptedException {
byte[] content = convertFileToBytes("D://old files/test123.pdf");
print(content, "ZDesigner GX420t");
}
private static byte[] convertFileToBytes(String absoluteFilePath) throws IOException {
File file = new File(absoluteFilePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum;
(readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum); // no doubt here is 0
}
} catch (IOException ex) {
} finally {
if (fis != null) {
fis.close();
}
}
byte[] bytes = bos.toByteArray();
return bytes;
}
private static boolean print(byte[] byteArray, String reqPrinterId)
throws IOException, InterruptedException {
boolean isPrintedSuccessfully = false;
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
PrintService[] services = PrintServiceLookup.lookupPrintServices(
flavor, null);
if (services.length > 0) {
PrintService myService = null;
for (PrintService service: services) {
if (service.getName().contains(reqPrinterId)) {
myService = service;
break;
}
}
DocPrintJob printJob = myService.createPrintJob();
JobCompleteMonitor monitor = new JobCompleteMonitor();
printJob.addPrintJobListener(monitor);
Doc document = new SimpleDoc(byteArray, flavor, null);
try {
printJob.print(document, null);
monitor.waitForJobCompletion();
System.out.println("-------------------- Print Completed " + monitor.completed);
isPrintedSuccessfully = true;
} catch (Exception e) {
e.printStackTrace();
}
}
return isPrintedSuccessfully;
}
private static class JobCompleteMonitor extends PrintJobAdapter {
private boolean completed = false;
#Override
public void printJobCanceled(PrintJobEvent pje) {
signalCompletion();
}
#Override
public void printJobCompleted(PrintJobEvent pje) {
signalCompletion();
}
#Override
public void printJobFailed(PrintJobEvent pje) {
signalCompletion();
}
#Override
public void printJobNoMoreEvents(PrintJobEvent pje) {
signalCompletion();
}
private void signalCompletion() {
synchronized(JobCompleteMonitor.this) {
completed = true;
JobCompleteMonitor.this.notify();
}
}
public synchronized void waitForJobCompletion() {
try {
while (!completed) {
wait();
}
} catch (InterruptedException e) {
}
}
}
}
For Desktop integration:
File file = ...
if (Desktop.isDesktopAvailable()) {
Desktop.getDesktop().print(file);
}
I used Pramod code but before that I have to pass my printer id that is name of printer. I am getting byte array from my db.
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.DocFlavor;
try {
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(new Copies(1));
PrintService pss[] = PrintServiceLookup.lookupPrintServices(DocFlavor.INPUT_STREAM.GIF, pras);
if (pss.length == 0)
throw new RuntimeException("No printer services available.");
//You have to check which printer you want to print.
PrintService ps = pss[1];
logger.info("Printing to " + ps);
//Here I am calling Pramod method.
boolean result = PrintPDF.print(byteArray, ps.getName());
logger.info("result " + result);
}
catch (Exception ex){
System.out.println(ex.getMessage());
}
This is not answer, this code will call Pramod method which is precise solution.
Thanks
Related
I'm pulling my hair out as I cannot get the samples to work - hopefully someone can help..
I would like to DETECT if a docx and a doc file is password protected/encrypted. I have seen this posted in a few places but I cannot get it work - it doesnt throw an exception. Can someone see what I am doing wrong. Note I only need to detect the password..i dont want to open the document.
String fileLocation = "C:/myfile.docx";
File file = new File(fileLocation);
FileInputStream fis = new FileInputStream(file.getAbsolutePath());
POIFSFileSystem pfis = new POIFSFileSystem(fis);
try{
EncryptionInfo info = new EncryptionInfo(pfis);
EncryptionMode mode = info.getEncryptionMode();
Decryptor d = Decryptor.getInstance(info);
//Try and open it
if(!d.verifyPassword(Decryptor.DEFAULT_PASSWORD))
{
//file is encrypted
}
}
catch(GeneralSecurityException gse)
{
//file is encrypted
}
catch(EncryptedDocumentException edc)
{
//file is encrypted
}
I haven't elaborated much to get the code smaller, but I've simply taken one of the factory classes - like SlideShowFactory - and modified it for H/XWPF. As H/XWPF hasn't got a common interface on the document level (as of now), the quick&dirty approach is to return an Object.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
public class EncDetect {
public static void main(String[] args) {
String dir = "/home/kiwiwings/project/poi/poi/test-data";
String[] files = {
"document/bug53475-password-is-solrcell.docx",
"document/password_tika_binaryrc4.doc",
"document/58067.docx",
"document/58804.doc"
};
for (String f : files) {
try {
DocumentFactory.create(new File(dir, f));
System.out.println(f + " not encrypted");
} catch (EncryptedDocumentException e) {
System.out.println(f + " is encrypted");
} catch (Exception e) {
System.out.println(f + " " +e.getMessage());
}
}
}
static class DocumentFactory {
public static Object create(NPOIFSFileSystem fs) throws IOException {
return create(fs, null);
}
public static Object create(final NPOIFSFileSystem fs, String password) throws IOException {
DirectoryNode root = fs.getRoot();
// Encrypted OOXML files go inside OLE2 containers, is this one?
if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
InputStream stream = null;
try {
stream = DocumentFactoryHelper.getDecryptedStream(fs, password);
return createXWPFDocument(stream);
} finally {
IOUtils.closeQuietly(stream);
}
}
// If we get here, it isn't an encrypted XWPF file
// So, treat it as a regular HWPF one
boolean passwordSet = false;
if (password != null) {
Biff8EncryptionKey.setCurrentUserPassword(password);
passwordSet = true;
}
try {
return createHWPFDocument(fs);
} finally {
if (passwordSet) {
Biff8EncryptionKey.setCurrentUserPassword(null);
}
}
}
public static Object create(InputStream inp) throws IOException, EncryptedDocumentException {
return create(inp, null);
}
public static Object create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
// If clearly doesn't do mark/reset, wrap up
if (! inp.markSupported()) {
inp = new PushbackInputStream(inp, 8);
}
// Ensure that there is at least some data there
byte[] header8 = IOUtils.peekFirst8Bytes(inp);
// Try to create
if (NPOIFSFileSystem.hasPOIFSHeader(header8)) {
NPOIFSFileSystem fs = new NPOIFSFileSystem(inp);
return create(fs, password);
}
if (DocumentFactoryHelper.hasOOXMLHeader(inp)) {
return createXWPFDocument(inp);
}
throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
}
public static Object create(File file) throws IOException, EncryptedDocumentException {
return create(file, null);
}
public static Object create(File file, String password) throws IOException, EncryptedDocumentException {
return create(file, password, false);
}
public static Object create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
if (!file.exists()) {
throw new FileNotFoundException(file.toString());
}
NPOIFSFileSystem fs = null;
try {
fs = new NPOIFSFileSystem(file, readOnly);
return create(fs, password);
} catch(OfficeXmlFileException e) {
IOUtils.closeQuietly(fs);
return createXWPFDocument(file, readOnly);
} catch(RuntimeException e) {
IOUtils.closeQuietly(fs);
throw e;
}
}
protected static Object createHWPFDocument(NPOIFSFileSystem fs) throws IOException, EncryptedDocumentException {
return new HWPFDocument(fs.getRoot());
}
protected static Object createXWPFDocument(InputStream stream) throws IOException, EncryptedDocumentException {
return new XWPFDocument(stream);
}
protected static Object createXWPFDocument(File file, boolean readOnly) throws IOException, EncryptedDocumentException {
try {
OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
return new XWPFDocument(pkg);
} catch (InvalidFormatException e) {
throw new IOException(e);
}
}
}
}
I'm working on a project that copies files with four threads.
I create List and store in there name of files to copy.
I want to use this 4 thread to work together, but I don't really get it how make it happend.
public class CopyingFiles implements Runnable
{
static File source = new File("C:\\test\\1\\");
static File dest = new File("C:\\test\\2\\");
#Override
public void run()
{
try
{
CopyingFromList(source, dest);
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void CopyFile(File sourceFile, File destination) throws IOException
{
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new FileInputStream(sourceFile);
outputStream = new FileOutputStream(destination);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0)
{
outputStream.write(buffer, 0 ,length);
}
} finally {
if(inputStream != null)
{
inputStream.close();
}
if(inputStream != null)
{
outputStream.close();
}
}
}
public static void CopyingFromList(File source, File dest) throws IOException, InterruptedException
{
List<String> fileList = FilesList.CreateFilesList(source);
for(String file : fileList)
{
System.out.println(Thread.currentThread().getName() + " > " + FilesList.DestinationOfFile(source) + file + " > " + FilesList.DestinationOfFile(dest) + file );
CopyFile(new File(FilesList.DestinationOfFile(source) + file), new File(FilesList.DestinationOfFile(dest) + file));
}
}
}
AND SECOND CLASS
public class FilesList
{
static File source = new File("C:\\test\\1\\");
static File source1 = new File("C:\\test\\3\\");
static File dest = new File("C:\\test\\2\\");
static File dest1 = new File("C:\\test\\4\\");
public static List<String> CreateFilesList(File source) throws InterruptedException, IOException
{
List<String> fileList = new ArrayList<>(Arrays.asList(source.list()));
return fileList;
}
public static String DestinationOfFile(File source)
{
return new String(source + "\\");
}
public static void PrintWholeList(File source) throws IOException, InterruptedException
{
List<String> fileList = CreateFilesList(source);
for(String file : fileList)
{
System.out.println(DestinationOfFile(source) + file);
}
}
public static void main(String []args) throws IOException, InterruptedException
{ /*
//CopyingFiles.CopyFile(new File(source+"\\file1.txt"), new File(dest+"\\file1.txt"));
//CopyingFiles.CopyingFromList(source,dest);
CopyingFiles t1 = new CopyingFiles();
CopyingFiles t2 = new CopyingFiles();
CopyingFiles t3 = new CopyingFiles();
CopyingFiles t4 = new CopyingFiles();
t1.start();
t2.start();
t3.start();
t4.start();
*/
ExecutorService executorService = Executors.newFixedThreadPool(5);
System.out.println(Thread.activeCount());
executorService.submit(() -> {
try
{
CopyingFiles.CopyingFromList(source,dest);
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
executorService.shutdown();
}
});
}
}
Could anyone help me,or show some other way to solve my problem.
I don't actually get what the problem is. This one works for me (and it is almost your program, just cleaned up a bit):
package multicp;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
/**
* Copy files using threads.
*/
public class Multicp {
public static void main(String[] args) {
// List of source/dest pairs ("tasks")
List<CopierCallable<Void>> opsList = new ArrayList<>();
opsList.add(new CopierCallable<>(Paths.get("f1src.dat"), Paths.get("f1dest.dat")));
opsList.add(new CopierCallable<>(Paths.get("f2src.dat"), Paths.get("f2dest.dat")));
opsList.add(new CopierCallable<>(Paths.get("f3src.dat"), Paths.get("f3dest.dat")));
opsList.add(new CopierCallable<>(Paths.get("f4src.dat"), Paths.get("f4dest.dat")));
ExecutorService execSvc = Executors.newFixedThreadPool(2); // 4 in your case. 2 is just for testing
try {
execSvc.invokeAll(opsList);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
execSvc.shutdown();
}
}
}
/**
* Performs actual copying from one source to one destination.
*/
class CopierCallable<Void> implements Callable<Void> {
private Path pathFrom;
private Path pathTo;
public CopierCallable(Path pathFrom, Path pathTo) {
this.pathFrom = pathFrom;
this.pathTo = pathTo;
}
#Override
public Void call() {
try {
// REPLACE_EXISTING is destructive, uncomment at your own risk
Files.copy(pathFrom, pathTo, COPY_ATTRIBUTES /*, REPLACE_EXISTING*/);
System.out.println(pathFrom + " copied");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I can see files being copied simultaneously in groups (by 2 for testing; replace with 4, but it would make initialization code larger for no profit).
I have 5 printers in Windows 8.1 and the PDF file is not in local system its generated in PHP server.
Question. how can i get the PDF file from the server and print to a specific printer?
I am trying with Apache PDFBox 2.0.0
EDIT:
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPageable;
public class JPrint {
public static boolean saveFile(URL url, String file) throws IOException {
boolean download_status = false;
System.out.println("[OK] - open");
InputStream in = url.openStream();
FileOutputStream fos = new FileOutputStream(new File(file));
System.out.println("[OK] - reading file...");
int length = -1;
byte[] buffer = new byte[1024];
while ((length = in.read(buffer)) > -1) {
fos.write(buffer, 0, length);
}
fos.close();
in.close();
download_status = true;
System.out.println("[OK] - downloaded");
return download_status;
}
public static void main(String[] args) throws IOException, PrinterException {
String downloaded_filename = "C:/Users/tpt/Downloads/pdf.pdf";
String download_pdf_from = "https://github.com/msysgit/msysgit/releases/download/Git-1.9.2-preview20140411/Git-1.9.2-preview20140411.exe";
String downloaded_filename_open_as_pdf = "C:\\Users\\tpt\\Downloads\\pdf.pdf";
String printerNameDesired = "DYMO LabelWriter 450"; // Brother HL-6180DW series
// Get printers
PrintService[] services = PrinterJob.lookupPrintServices();
DocPrintJob docPrintJob = null;
try{
URL url = new URL(download_pdf_from);
if(saveFile(url, downloaded_filename)) {
try {
PDDocument pdf = PDDocument.load(new File(downloaded_filename_open_as_pdf));
PrinterJob job = PrinterJob.getPrinterJob();
for (int i = 0; i < services.length; i++) {
if (services[i].getName().equalsIgnoreCase(printerNameDesired)) {
docPrintJob = services[i].createPrintJob();
}
}
job.setPrintService(docPrintJob.getPrintService());
job.setPageable(new PDFPageable(pdf));
//docPrintJob = service[i].createPrintJob();
job.print();
} catch (Exception e) {
System.out.println("[FAIL]" + e);
}
} else {
System.out.println("[FAIL] - download fail");
}
} catch (Exception ae) {
System.out.println("[FAIL]" + ae);
}
}
}
This gives you back a list of available printers:
PrintService[] services = PrinterJob.lookupPrintServices();
You can loop through this array and select the printer by name (services[i].getName())
I'm developing a JAVA program that prints a file.
I need to know when the printer has completed printing the file, I've found this simple code that it is interesting:
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");
}
}
So, the method that interest me is this:
public void printJobCompleted(PrintJobEvent pje) {
System.out.println("Completed");
}
but it doesn't works for me. The issue is that the printer doesn't support this type of code. Can someone tell me a model of printer that support this code?
Look at the sample code here:
It looks like you need to implement your PrintJobAdapter. The relevant bits are:
package com.your.package;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;
public class DetermineThatPrintJobHasFinished {
public static void main(String[] args) throws Exception {
//... see example in link
// Locate the default print service for this environment.
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
// Create and return a PrintJob capable of handling data from
// any of the supported document flavors.
DocPrintJob printJob = service.createPrintJob();
// register a listener to get notified when the job is complete
JobCompleteMonitor monitor = new JobCompleteMonitor();
printJob.addPrintJobListener(monitor);
// Construct a SimpleDoc with the specified print data, doc flavor and doc attribute set.
Doc doc = new SimpleDoc(is, flavor, null);
// Print a document with the specified job attributes.
printJob.print(doc, null);
monitor.waitForJobCompletion();
is.close();
}
private static class JobCompleteMonitor extends PrintJobAdapter {
private boolean completed = false;
#Override
public void printJobCanceled(PrintJobEvent pje) {
signalCompletion();
}
#Override
public void printJobCompleted(PrintJobEvent pje) {
signalCompletion();
}
#Override
public void printJobFailed(PrintJobEvent pje) {
signalCompletion();
}
#Override
public void printJobNoMoreEvents(PrintJobEvent pje) {
signalCompletion();
}
private void signalCompletion() {
synchronized (JobCompleteMonitor.this) {
completed = true;
JobCompleteMonitor.this.notify();
}
}
public synchronized void waitForJobCompletion() {
try {
while (!completed) {
wait();
}
} catch (InterruptedException e) {
}
}
}
}
it's not the best efficient but you could wait until the Attribute: 'queued-job-count' is equal to Zero :
public final static void waitEndJobs(final PrintService printService) throws InterruptedException {
int queue = 1;
while (queue != 0) {
final AttributeSet attributes = printService.getAttributes();
final Attribute a = Arrays.stream(attributes.toArray())//
.filter(o -> o.getName().equalsIgnoreCase("queued-job-count"))//
.findFirst()//
.orElse(null);
queue = Integer.parseInt(attributes.get(a.getClass()).toString());
Thread.sleep(5000);
}
}
To my point Rx or Project Reactor can very help with this old java printer api. I also have faced this problem recently, and currently I have finished on next version. maybe it will help to somebody
first, if you are using pdfbox as me, then
#Slf4j
#Service
#RequiredArgsConstructor
public class PrinterDeviceServiceImpl implements PrinterDeviceService {
#Override
public StreamEx<PrintService> getAvailablePrinters() {
return of(PrintServiceLookup.lookupPrintServices(null, null));
}
#Override
public boolean isPrinterExists(String printerName) {
return getAvailablePrinters()
.anyMatch(p -> p.getName().equals(printerName));
}
#Override
public PrintService getPrinter(String printerName) {
return getAvailablePrinters()
.findFirst(p -> p.getName().equals(printerName))
.orElse(null);
}
#Override
public Mono<PrintTaskStatus> print(String printerName, InputStream source) {
try {
PrintService printer = getPrinter(printerName);
if (printer == null) {
return Mono.error(new RuntimeException("printer is null"));
}
PDDocument document = Unchecked.supplier(() -> PDDocument.load(source));
PrinterJob job = PrinterJob.getPrinterJob();
job.setPageable(new PDFPageable(document, Orientation.PORTRAIT));
job.setPrintService(printer);
Paper paper = new Paper();
paper.setSize(500, 500); //TODO: lets get it from configs or task request
paper.setImageableArea(0.0, 0.0, paper.getWidth(), paper.getHeight()); // no margins
// custom page format
PageFormat pageFormat = new PageFormat();
pageFormat.setPaper(paper);
Book book = new Book();
book.append(new PDFPrintable(document), pageFormat, document.getNumberOfPages());
job.setPageable(book);
HashPrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
attr.add(OrientationRequested.PORTRAIT);
attr.add(PrintQuality.HIGH);
job.print(attr);
return Mono.create(sink -> {
/*If exec thread is UI or from http pool, then maybe better idea is to attach it to another independent one or run print in another one!*/
while (!isPrintCompleted(printer)) {
log.debug("I'm waiting to printer processed queue");
Unchecked.runnable(() -> Thread.sleep(1000));
}
/*you can wait some fixed or dynamic time based on how big your document etc and finish with error state if it needed*/
log.debug("printer queue have processed :)");
sink.success(PrintTaskStatus.Completed);
});
} catch (Throwable ex) {
ExceptionHelpers.logError(ex, log);
return Mono.just(PrintTaskStatus.Failed);
}
}
private boolean isPrintCompleted(PrintService printer) {
return Arrays.stream(printer.getAttributes().toArray())
.filter(att -> att instanceof QueuedJobCount)
.map(QueuedJobCount.class::cast)
.findFirst()
.map(queuedJobCount -> queuedJobCount.getValue() == 0)
.orElse(false);
}
}
second, if you are preferred only default printer api then replace print method to:
#Override
public Mono<PrintTaskStatus> print(String printerName, InputStream source) {
PrintService printer = getPrinter(printerName);
if (printer == null) {
return Mono.error(new RuntimeException("printer is null"));
}
try {
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
DocPrintJob printJob = printer.createPrintJob();
CustomPrintJobListener monitor = new CustomPrintJobListener();
printJob.addPrintJobListener(monitor);
Doc doc = new SimpleDoc(source, flavor, null);
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(OrientationRequested.PORTRAIT);
pras.add(PrintQuality.NORMAL);
pras.add(new Copies(1));
printJob.print(doc, pras);
return monitor.getJobMono();
} catch (Exception ex) {
ExceptionHelpers.logError(ex, log);
return Mono.just(PrintTaskStatus.Failed);
}
}
#Slf4j
private static class CustomPrintJobListener extends PrintJobAdapter {
private final EmitterProcessor<PrintTaskStatus> emitter = EmitterProcessor.create();
#Override
public void printJobCanceled(PrintJobEvent pje) {
emitter.onNext(PrintTaskStatus.Canceled);
log.info("Print job canceled :| ");
}
#Override
public void printDataTransferCompleted(PrintJobEvent pje) {
log.info("Print data transfer completed ;) ");
}
#Override
public void printJobCompleted(PrintJobEvent pje) {
emitter.onNext(PrintTaskStatus.Completed);
log.info("Print job completed :) ");
}
#Override
public void printJobFailed(PrintJobEvent pje) {
emitter.onNext(PrintTaskStatus.Failed);
log.info("Print job failed :( ");
}
#Override
public void printJobNoMoreEvents(PrintJobEvent pje) {
emitter.onNext(PrintTaskStatus.Completed);
log.info("No more events to the job :|");
}
#Override
public void printJobRequiresAttention(PrintJobEvent pje) {
log.info("Print job requires attention :O ");
}
public Mono<PrintTaskStatus> getJobMono() {
return emitter.next();
}
}
Good luck :)
I'm using an IntentService to append single NMEA strings to a log file stored in the external public storage on an Android device, but I'm getting inconsistent behavior.
First off the log file does not appear when the device is connected for USB debugging. I read that many Android devices cannot write to external storage when connected via USB, but even when it is run disconnected from USB, it may take several times of turning it on and off and rerunning the applications before the log file appears in the file system. If I do not clear the log, I still have to restart the phone before it will begin appending to the file again.
How can I get the file to appear consistently everytime?
import android.app.IntentService;
import android.content.Intent;
public class LogFileService extends IntentService {
DebugLog debug = new DebugLog("LogFileService");
public static final String GPS_STR = "GPS_STR";
public static final String FILE_PATH = "FILE_PATH";
public static final String FILE_NAME = "gps_data.txt";
public LogFileService() {
super("LogFileService");
}
#Override
protected void onHandleIntent(Intent intent) {
debug.log("Handling intent");
String data = intent.getStringExtra(GPS_STR);
debug.log("Writing " + data);
GpsLogFile logFile = new GpsLogFile(FILE_NAME);
logFile.open();
logFile.write(data);
logFile.close();
}
#Override
public void onCreate() {
super.onCreate();
debug.log("Created");
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import android.content.Context;
import android.os.Environment;
public class GpsLogFile {
DebugLog debug = new DebugLog("LogFile");
private File filePath = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS
);
private File logFile = null;
private String fileName = null;
private PrintWriter fileOut = null;
public GpsLogFile(String name) {
fileName = name;
}
public void open() {
try {
filePath.mkdirs();
if (!isExternalMediaAvailable()) {
throw new IOException("External media not available.");
}
logFile = new File(filePath, fileName);
//logFile.mkdirs();
if (!logFile.exists()) {
logFile.createNewFile();
}
fileOut = new PrintWriter(
new FileOutputStream(logFile.getAbsolutePath(), true)
);
} catch (IOException e) {
debug.log("Unable to open file.");
debug.log(e.getMessage());
}
}
public void write(String data) {
debug.log("Writing to " + logFile.getAbsolutePath() + " " + data);
try {
fileOut.write(data);
//fileOut.newLine();
checkPrintWriterError(fileOut);
fileOut.flush();
} catch (IOException e) {
debug.log("Unable to write");
debug.log(e.getMessage());
}
}
public void close() {
if (null != fileOut) {
try {
fileOut.close();
checkPrintWriterError(fileOut);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void checkPrintWriterError(PrintWriter writer) throws IOException {
if (true == writer.checkError()) {
throw new IOException("Print writer error.");
}
}
}