Para llevar a cabo la solución, vamos a utilizar una implementación open source (Project Tyrus) de la especificación JSR 356 - Java API for WebSocket para establecer la comunicación entre la aplicación web y el servidor que deberá estar ejecutándose en la maquina cliente y que recibirá mediante WebSocket el documento a imprimir y enviar este a la impresora. A continuación los pasos a realizar utilizando el IDE IntelliJ IDEA:
PASO 1: Creación del proyecto Tyrus donde se definirá el WebSocket endpoint y el servidor
PASO 2: Agregar las dependencias maven necesarias para la creación de nuestro servidor Tyrus
    <dependencies>
        <dependency>
            <groupId>org.glassfish.tyrus</groupId>
            <artifactId>tyrus-server</artifactId>
            <version>1.13</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.tyrus</groupId>
            <artifactId>tyrus-container-grizzly-server</artifactId>
            <version>1.13</version>
        </dependency>
    </dependencies>
PASO 3: Implementación del endpoint server FileServerEndpoint
package ws.serverprinter.server;
import java.io.*;
import java.nio.ByteBuffer;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/receive/fileserver")
public class FileServerEndpoint {
    static ByteArrayOutputStream baos = null;
    @OnOpen
    public void open(Session session, EndpointConfig conf) {
        System.out.println("FileServerEndpoint is open");
    }
    @OnMessage
    public void processUpload(ByteBuffer msg, boolean last, Session session) {
        System.out.println("ByteBuffer message");
        while(msg.hasRemaining()) {
            baos.write(msg.get());
        }
    }
    @OnMessage
    public void message(Session session, String msg) {
        System.out.println("Message: " + msg);
        if(!msg.equals("end")) {
            baos = new ByteArrayOutputStream();
        }else {
            try {
                baos.flush();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @OnClose
    public void close(Session session, CloseReason reason) {
        System.out.println("WebSocket closed: "+ reason.getReasonPhrase());
    }
    @OnError
    public void error(Session session, Throwable t) {
        t.printStackTrace();
    }
}
PASO 4: Implementación de la aplicación principal y el server Tyrus
package ws.serverprinter.server;
import org.glassfish.tyrus.server.Server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
 * Created by williams on 19-07-16.
 */
public class MainApp {
    public static void main(String[] args) {
        runServer();
    }
    private static void runServer() {
        Server server = new Server("localhost", 8025, "/websockets", null, FileServerEndpoint.class);
        try {
            server.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("Press a key to stop the server.");
            reader.readLine();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            server.stop();
        }
    }
}
PASO 5: Desarrollo de la aplicación cliente
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Chat</title>
</head>
<body>
<h2>File Upload</h2>
Select file
<input type="file" id="filename" />
<br>
<input type="button" value="Connect" onclick="connect()" />
<br>
<input type="button" value="Upload" onclick="sendFile()" />
<script>
    var ws;
    function connect() {
        ws = new WebSocket("ws://localhost:8025/websockets/receive/fileserver");
        ws.binaryType = "arraybuffer";
        ws.onopen = function() {
            alert("Connected.")
        };
        ws.onmessage = function(evt) {
            alert(evt.msg);
        };
        ws.onclose = function() {
            alert("Connection closed...");
        };
        ws.onerror = function(e) {
            alert(e.msg);
        }
    }
    function sendFile() {
        var file = document.getElementById('filename').files[0];
        ws.send('filename:'+file.name);
        var reader = new FileReader();
        var rawData = new ArrayBuffer();
        reader.loadend = function() {}
        reader.onload = function(e) {
            rawData = e.target.result;
            ws.send(rawData);
            alert("file transferred.")
            ws.send('end');
        }
        reader.readAsArrayBuffer(file);
    }
</script>
</body>
</html>
PASO 6: Implementación del servicio de impresión
    @OnMessage
    public void message(Session session, String msg) {
        System.out.println("Message: " + msg);
        if(!msg.equals("end")) {
            baos = new ByteArrayOutputStream();
        }else {
            try {
                baos.flush();
                baos.close();
                print(baos);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (PrintException e) {
                e.printStackTrace();
            }
        }
    }
    private void print(ByteArrayOutputStream baos) throws PrintException {
        PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
        if (services.length > 0) {
            DocFlavor psInFormat = DocFlavor.INPUT_STREAM.AUTOSENSE;
            Doc myDoc = new SimpleDoc(new ByteArrayInputStream(baos.toByteArray()), psInFormat, null);
            DocPrintJob job = services[0].createPrintJob();
            job.print(myDoc, null);
        }
    }
PASO 7: Iniciamos el server Tyrus
PASO 8: Adjuntamos algún archivo PDF desde nuestra aplicación cliente y lo enviamos al server
Se puede observar como el archivo se envió directamente a la impresora.
Fuentes:
https://tyrus.java.net/documentation/1.13/user-guide.html#standalone-mode http://stackoverflow.com/questions/21769470/file-upload-using-java-websocket-api-and-javascript http://docs.oracle.com/javase/7/docs/api/javax/print/package-summary.html https://java.net/projects/websocket-spec
Github: https://github.com/ghwrivas/server-printer-ws






