Some of my java code, but is for a raw websocket, dont using STOMP.
Based on this javascript recconnecting implementation: https://github.com/joewalnes/reconnecting-websocket
Java code:
/**
 * 
 * Problemas conocidos:
 * 
 *  Si se realiza la instancia dos veces consecutivas, se generan dos conexiones. Esto es debido a que el Executor
 *   crea dos tareas y no limita.
 * Una posible solucion seria convertir esta API de reconexion en un Singleton, sin embargo hacer eso significa solo
 *  poder crear una coneccion.
 * Una forma de solucionar esto es crear una fabrica de websockets. Y por otro lado tener la API como un singleton. 
 *   
 * Para reproducir el problema:
 * 
 *      ReconnectWebsocket ws = new ReconnectWebsocket(new LogicWsExternal() {
            @Override
            public void onOpen(Session session) {
            }   // This is myPersonalEndPoint
            },uri, settings
        );
        ws = new ReconnectWebsocket(new LogicWsExternal() {
            @Override
            public void onOpen(Session session) {
            }   // This is myPersonalEndPoint
            },uri, settings
        );
        // .. dos conexiones...
 * 
 * 
 * 
 * @author gas
 *
 */
public class ReconnectWebsocket implements ReconnectObserver{
    private final Logger LOG = LoggerFactory.getLogger(ReconnectWebsocket.class);
    //http://stackoverflow.com/questions/5762491/how-to-print-color-in-console-using-system-out-println
    public static final String ANSI_RESET = "\u001B[0m";
    public static final String ANSI_BLUE = "\u001B[34m";
    public static final String ANSI_WHITE = "\u001B[37m";
    // private static ReconnectWebsocketTest instance = null;
    Boolean debug;
    Boolean automaticOpen;
    Integer reconnectInterval;
    Integer maxReconnectionInterval;
    Float reconnectDecay;
    Integer timeoutInterval;
    Integer maxConnectAttempts;
    String binaryType;
    // These should be treated as read-only properties
    /** The URL as resolved by the constructor. This is always an absolute URL. Reas only. */
    URI path;
    /** The number of attempted reconnects since starting, or the last successful connection. Read only. */
    int connectAttemptsCount;
    /**
    * The current state of the connection.
    * Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
    * Read only.
    */
    WebSocketStates readyState = WebSocketStates.CLOSED;
    /**
     * A string indicating the name of the sub-protocol the server selected; this will be one of
     * the strings specified in the protocols parameter when creating the WebSocket object.
     * Read only.
     */
    // TODO
    //this.protocol = null;
    // Private state variables
    //ReconnectWebsocket self = this;
    Session session;                    // In Javascript implementation is ws variable.
    boolean forcedClose = false;
    boolean timeOutFlag = false;
    Future<Boolean> timerReconnectionFuture;            // Usado para controlar el timer para las reconexnes.
    //private ReconnectObservable observable;
    LogicWsExternal logicExternal;
    ClientManager client;
    LogicWs wsLogic;
    static ScheduledExecutorService executor;
    static ScheduledExecutorService executor2;
    Future openFuture;
    AtomicBoolean openFlag;
    /*
     * 
     * Tyrus estates:
     *      org.glassfish.tyrus.core.TyrusWebSocket.State
     * 
     * */
    public static enum WebSocketStates {                //  Tyrus:
        CONNECTING("CONNECTING",0)      //      NEW
        ,OPEN("OPEN",1)                 //      CONNECTED
        ,CLOSING("CLOSING",2)           //      CLOSING
        ,CLOSED("CLOSED",3)             //      CLOSED
        ;
        String desc;
        Integer statusInt;
        WebSocketStates(String desc,Integer statusInt){
            this.desc=desc;
            this.statusInt=statusInt;
        }
        public String getDescription() {
            return desc;
        }
        public Integer getStatusInt() {
            return statusInt;
        }
        public void printDescription(){
            System.out.println("PrinterStatus: "+desc);
        }
    }
    public ReconnectWebsocket(URI path) throws DeploymentException, IOException {
        this(new LogicWsExternal(){
            @Override
            public void onOpen(Session session) { }},path, null);
    }
    // Consturctor whith Only package visivility
    public ReconnectWebsocket(LogicWsExternal logicWsExernal, URI path) throws DeploymentException, IOException {
        this(logicWsExernal,path, null);
    }
    public ReconnectWebsocket(LogicWsExternal logicWsExternal, URI path, ReconnectSettings settings) {
        // Default setting
        // Overwrite and define settings with options if they exist.
        /** Wheter this instance should log debug mesages. */
        this.debug = settings.getDebug()!=null ? settings.getDebug() : true;
        /** Wheter or not the websocket should attempt to connect immediately upon instantiation. */
        this.automaticOpen = settings.getAutomaticOpen() !=null ? settings.getAutomaticOpen() : true;
        /** The number of milliseconds to delay before attempting to reconnect. */
        this.reconnectInterval = settings.getReconnectInterval()!=null ? settings.getReconnectInterval() : 1000;
        /** The maximum number of milliseconds to delay a reconnection attempt. Timeout to reconnect */
        this.maxReconnectionInterval = settings.getMaxReconnectionInterval()!=null ? settings.getMaxReconnectionInterval() : 10000;
        /** The rate of increase of the reconnect delay. Allows reconnect attemps to back off when problems persist. */
        this.reconnectDecay = settings.getReconnectDecay()!=null ? settings.getReconnectDecay() : (float) 1.3;
        /** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying */
        this.timeoutInterval = settings.getTimeoutInterval()!=null ? settings.getTimeoutInterval() : 5000;
        /** The number of connection attempts to make before to stop. Unlimited if value is zero.
        **/
        this.maxConnectAttempts = settings.getMaxConnectAttempts()!=null ? settings.getMaxConnectAttempts() : 0;
        /** The binary type, possible values 'blob' or 'arraybuffer', default 'blob'. */
        this.binaryType = settings.getBinaryType()!=null ? settings.getBinaryType() : "blob";
        //settings.put("idStateEvenbusChannel", "false");
        //settings.put("idStateEvenbusChannel", "false");
        // These should be treated as read-only properties
        /** The URL as resolved by the constructor. This is always an absolute URL. Reas only. */
        this.path = path;
        /** The number of attempted reconnects since starting, or the last successful connection. Read only. */
        this.connectAttemptsCount = 0;
        /**
        * The current state of the connection.
        * Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
        * Read only.
        */
        this.readyState = WebSocketStates.CLOSED;
         /**
         * A string indicating the name of the sub-protocol the server selected; this will be one of
         * the strings specified in the protocols parameter when creating the WebSocket object.
         * Read only.
         */
        // TODO 
         // "has a" rather than "is a" observable
        //observable = new ReconnectObservable();
        this.logicExternal = logicWsExternal;
        wsLogic = new LogicWs();
        //client =  ClientManager.createClient();//GLiszli lient by default
        // Java 7 cient. 
        client = ClientManager.createClient(JdkClientContainer.class.getName());
        wsLogic.addObserver(this);
        // By default initialize the executors.
        executor = Executors.newScheduledThreadPool(1);
        executor2 = Executors.newScheduledThreadPool(1);
        openFlag = new AtomicBoolean(true);
        // Wheher or not to create a websocket upon instantiation
        if (this.automaticOpen) {
            //this.open();
            this.open();
        }
    }
    public void open() {
        if (readyState == WebSocketStates.CONNECTING || readyState == WebSocketStates.OPEN ) {
            return;
        }
        if (executor.isShutdown()) {
            executor = Executors.newScheduledThreadPool(1);
        }
        if (executor2.isShutdown()) {
            /*
             * Este poolthread se apaga cuando se manda a llamar la funcion close() de la API.
             * El apagado se realiza porque se considera que ya no se va o volver a conectar.
             */
            executor2 = Executors.newScheduledThreadPool(1);
        }
        /*
         * Resetear variables
         */
        AtomicInteger counter = new AtomicInteger(0);
        connectAttemptsCount = 0;
        readyState = WebSocketStates.CONNECTING;
        // Ejecutar funciones en metodo OnConnecting
        //String reconnectReason = e.getMessage();
        //self.update(new InternalMessageWs(WsEventType.ONCONNECTING,new OnConnectingEvent(reconnectReason)));
        update(new InternalMessageWs(WsEventType.ONCONNECTING,new OnConnectingEvent("First Connect")));
        Runnable openRun = () -> {
            do{
                if (debug) {
                    System.out.println("DEBUG: ReconnectingWebSocket attempt-connect# "+(connectAttemptsCount+1)+" of "+(maxConnectAttempts==0?"infinite":maxConnectAttempts)+" URI="+path.getPath());
                }
                Callable<Session> task1 = new Callable<Session>() {
                    @Override
                    public Session call() throws Exception {
                        // Avizar al API que se esta intentando realizar una reconexión. Patron productor-consumidor.
                        // TODO Deberia de ser un hilo?? ESto ya que podria se r que algo en el metodo externo sea de tipo bloqueante.
                        watcherReconnectionTry();
                        Session session = client.connectToServer(wsLogic,path);
                        //self.session = client.connectToServer(wsLogic,self.path);
                        //System.out.println("ReconnectWebsocket:: client.connectToServer(...) is null:"+(session==null?"true":"false"));
                        //System.out.println("ReconnectWebsocket:: client.connectToServer(...) is open:"+session.isOpen());
                        return session;
                    }
                };
                Future<Session> future = executor.submit(task1);
                try {
                    // Tiempo de espera antes de interrumpir volver a intentarlo.
                    //Session s = future.get(self.timeoutInterval,TimeUnit.MILLISECONDS);
                    //Session s = future.get(30,TimeUnit.SECONDS);
                    //return s;
                    //self.session = future.get(30,TimeUnit.SECONDS);
                    session = future.get(timeoutInterval,TimeUnit.MILLISECONDS);
                    break;
                } catch (InterruptedException | ExecutionException | TimeoutException e) {
                    // TODO Auto-generated catch block
                    //e.printStackTrace();          //For debug only
                    // Calculate Back off time.
                    /*
                     * 
                     */
                    float timeout = (float) (reconnectInterval * Math.pow(reconnectDecay,connectAttemptsCount));
                    connectAttemptsCount++;
                    if (maxConnectAttempts > 0 && ( connectAttemptsCount >= maxConnectAttempts )) {
                        break;
                    }
                    int maxTimeReconnect = (int) (timeout > maxReconnectionInterval ? maxReconnectionInterval : timeout);
                    counter.set(maxTimeReconnect/1000);
                    Callable<Boolean> timerReconnection = new Callable<Boolean>() {
                        @Override
                        public Boolean call() {
                            System.out.println("counter.get()="+counter.get());
                            while(counter.get() >= 0) {
                                System.out.println("Time next reconection: "+counter.get()+" seconds");
                                System.out.println("ThreadId: "+Thread.currentThread().getId() );
                                // Avizar a la API el tiempo para la sig. reconexión.. Patron productor-consumidor.
                                // TODO Deberia de ser un hilo?? ESto ya que podria se r que algo en el metodo externo sea de tipo bloqueante.
                                watcherTimeLeft(counter.get());
                                if (counter.get() == 0 && debug ) {
                                    System.out.println("DEBUG: ReconnectingWebSocket connection-timeout: "+path.getPath());
                                    break;
                                }
                                try {
                                    Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                                counter.decrementAndGet();
                            }
                            return false;
                        }
                    }; 
                    /*
                     *          scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS)
                     * 
                     * 0 -> initialDelay,  this time is includen in the backoff algorithm calc, then this value is zero.
                     * timeout -> the delay between the termination of one execution and the commencement of the next
                     */
                    timerReconnectionFuture = executor.submit(timerReconnection);
                    try {
                        Boolean delayTime = timerReconnectionFuture.get();
                    } catch (InterruptedException | ExecutionException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }while (!Thread.currentThread().isInterrupted()); //END while
            //while (openFlag.get()); //END while   
        };// END Runnable
        openFuture = executor2.submit(openRun);
    }//
    public void send(String str) {
        // Convertir el texto a objeto Message para enviarlo.
        if (readyState ==  WebSocketStates.OPEN) {
            if (debug) {
                LOG.debug("Sending to URL:\"{}\", Data:\n\"{}\" ",path.getPath(),JsonWriter.formatJson(str));
                //System.out.println("DEBUG: ReconnectingWebSocket sending to "+path.getPath()+": "+str);
            }
            //session.getBasicRemote().sendText(data);
            try {
                session.getBasicRemote().sendText(str);
            } catch (IOException e) {
                LOG.error("Sending to URL:\"{}\", Data:\"{}\" {}",path.getPath(),str,e);
                //e.printStackTrace();
            }
        }
    }
    /**
     * 
     * @param j objeto Json a enviar por Websocket.
     * @throws EncodeException 
     * @throws IOException 
     */
    public void send(Json j) {
        //System.out.println("ReconnectWebsocket:: send(Json INI)");
        send(new Message(j));
        //System.out.println("ReconnectWebsocket:: send(Json END)");
    }
     /**
     * Transmits data to the server over Websocket connection.
     *
     * @param data a text string, ArrayBuffer or Blob to send to the server.
     * @throws IOException 
     * @throws EncodeException 
     */
    public void send(Message data) {
        //System.out.println("ReconnectWebsocket:: send(Message INI)");
        if (readyState ==  WebSocketStates.OPEN) {
            if (debug) {
                System.out.println("DEBUG: ReconnectingWebSocket send "+path.getPath()+": "+data);
            }
            //System.out.println("ReconnectWebSocket::send(Message msg - Before)" );
            //System.out.println("ReconnectWebSocket::send(Message msg - Before - session is null="+(session==null?"true":"false" ));
            //System.out.println("ReconnectWebSocket::send(Message msg - Before - session is open="+session.isOpen());
            //session.getBasicRemote().sendText(data);
            try {
                session.getBasicRemote().sendObject(data);
                LOG.debug("Sending to URL:\"{}\", Data:\"{}\" ",path.getPath(),data);
                //System.out.println("REconnectWebSocket::send(Message msg -  After)" );
            } catch (IOException | EncodeException e) {
                //e.printStackTrace();
                LOG.error("Sending to URL:\"{}\", Data:\"{}\" {}",path.getPath(),data,e);
            }
        }
        // Deberia de detenerse la reconeccion en estos casos?, es decir detener despues de intentar enviar una
        //  cadena de texto pero que ha fallado.
        //System.out.println("ReconnectWebsocket:: send(Message END)");
    }
    public void close(String reason) {
        close(CloseReason.CloseCodes.NORMAL_CLOSURE,reason);
    }
    public void close() {
        close(CloseReason.CloseCodes.NORMAL_CLOSURE,null);
    }
    public void close(CloseReason.CloseCodes code) {
        close(code,null);
    }
    /** Closes the Websocket connection or connection attempt, if any.
     *  If the connection is already CLOSED, this method does nothing.
     */
    public void close(CloseReason.CloseCodes code, String reason) {
        if (readyState == WebSocketStates.CLOSED) {
            return;
        }
        CloseReason closeReason;
        forcedClose = true;
        /*
         * Status code:     1000
         * Name:            CLOSE_NORMAL
         * Description:     The connection successfully completed whatever purpose for
         *                   which it was created.
         *  https://developer.mozilla.org/es/docs/Web/API/CloseEvent
        */
        // Default CLOSE_NORMAL code
        if (code==null) {
            closeReason = new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE,"ReconnectingWebSocket STOP");
        } else if (reason!=null) {
            closeReason = new CloseReason(code,reason);
        } else {
            closeReason = new CloseReason(code,"ReconnectingWebSocket STOP");
        }
        if ( (readyState == WebSocketStates.OPEN || readyState == WebSocketStates.CONNECTING) ) {
            // Change readyState status:
            readyState = WebSocketStates.CLOSED;
            if (session==null) {
                /*
                 * readyState == WebSocketStates.CONNECTING && session == null
                 * 
                 * This ocurr when the server is off and the client is in a loop trying to connect.
                 */
                timerReconnectionFuture.cancel(true);
                //openFuture.cancel(true);
            } else {
                /*              
                 * readyState == WebSocketStates.OPEN && session != null
                 *  or
                 * readyState == WebSocketStates.CONNECTING && session != null
                 */
                try { // Permanent close. Called via the Close method.
                    if (session.isOpen()) {
                        /*
                         * Session is previously closed when has connected at less one time, after the server shutdown
                         * and the reconnection beging. During the reconnection if you try to close (forced close)
                         * then session.close will thorwn a error.
                         * To fix we have verificate if the session is closed.
                         */
                        session.close(closeReason);
                    }
                    executor.shutdown();
                    executor2.shutdown();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    LOG.error("Error cerrando sesion. {}",e);
                }
            }
            //openFuture.cancel(true);
        }
    }
    /**
     * Additional public API method to refresh the connection if still is open.
     * After close, the websocket will try to reconnect.
     * For example, if the app suspects bad data / missed heart beats, it can try to refresh.
     */
    public void refresh() {
        if (readyState == WebSocketStates.OPEN) {
            try {
                session.close(new CloseReason(CloseCodes.SERVICE_RESTART, "refresh!!"));
            } catch (IOException e) {
                //e.printStackTrace();
                LOG.error("Error cerrando sesion. {}",e);
            }
        } else {
            // Stop timer of reconnection.
            if (readyState == WebSocketStates.CONNECTING) {
                //timerReconnectionFuture.cancel(true);
                close(CloseCodes.SERVICE_RESTART, "refresh!!");
                // Reset variables.
                connectAttemptsCount = 0;
                open();
            }
        }
    }
    public Session getSession(){
        return session;
    }
    public WebSocketStates getReadyState() {
        return readyState;
    }
    /**
     * El observador de los cambios en el clente Websocket interno.
     */
    @Override
    public void update(InternalMessageWs msg) {
        switch (msg.getType()) {
        case ONOPEN:
            // Cambiar estado de la conexión
            readyState = WebSocketStates.OPEN;
            if (debug ) {
                System.out.println("DEBUG: ReconnectingWebSocket onOpen: "+path.getPath());
            }
            // Ejecutar las funciones onOPen que el usuario ha definido.
            logicExternal.onOpen( ((OnOpenEvent)msg.getEvent()).getSession() );
        break;
        case ONMESSAGE:
            if (debug) {
                System.out.println("DEBUG: ReconnectingWebSocket onMessage: "+path.getPath());
            }
            OnMessageEvent evtMsg = (OnMessageEvent)msg.getEvent();
            // Ejecutar las funciones OnMessage que el usuario ha definido.
            logicExternal.onMessage(evtMsg.getSession(),evtMsg.getMessage());       
        break;
        case ONCLOSE:
            if (debug ) {
                System.out.println("DEBUG: ReconnectingWebSocket onClose: "+path.getPath()+" forcedClose="+forcedClose);
            }
            // Cambiar estado de la conexión
            readyState = WebSocketStates.CLOSED;
            OnCloseEvent evtClose = (OnCloseEvent)msg.getEvent();
            // Ejecutar las funciones OnClose que el usuario ha definido.
            logicExternal.onClose(evtClose.getSession(),evtClose.getReason());
            /*
             * Determinar si se debe vlver a conectar o no.
             * Si forcedClose = true, entonces detener.
             * Si forcedClose = false, entonces reconectar.
             */
            if (!forcedClose) {
                this.open();
            }
            else{
                if (debug ) {
                    System.out.println("DEBUG: ReconnectingWebSocket STOP Reconnectiing: "+path.getPath());
                }
                forcedClose = false;
            }
        break;
        case ONERROR:
            if (debug ) {
                System.out.println("DEBUG: ReconnectingWebSocket onError: "+path.getPath());
            }
            // Cambiar estado de la conexión
            readyState = WebSocketStates.CLOSED;
            OnErrorEvent evtError = (OnErrorEvent)msg.getEvent();
            // Ejecutar las funciones OnError que el usuario ha definido.
            logicExternal.onError(evtError.getSession(),evtError.getT());
            // Volver a iniciar secuencia de conectar.
            this.open();
            // Algunos prfieren cerrar la conexion.
            //this.close(CloseCodes.CLOSED_ABNORMALLY,evtError.getT().getMessage());
        break;
        case ONCONNECTING:
            if (debug ) {
                System.out.println("DEBUG: ReconnectingWebSocket onConnecting: "+path.getPath());
            }
            OnConnectingEvent evtConnecting = (OnConnectingEvent)msg.getEvent();
            // Ejecutar las funciones OnConnecting que el usuario ha definido.
            logicExternal.onConnecting(evtConnecting.getReason());
        break;
        default:
            break;
        }
    }
    @Override
    public void watcherReconnectionTry() {
        logicExternal.watcherReconnectionTry();
    }
    @Override
    public void watcherTimeLeft(int timeLeft) {
        logicExternal.watcherTimeLeft(timeLeft);
    }
}
One interface:
public interface ReconnectObserver {
    public void update(InternalMessageWs msg);
    public void watcherReconnectionTry();
    public void watcherTimeLeft(int timeLeft);
}
ReconnectObservable class:
import java.util.ArrayList;
public class ReconnectObservable implements ReconnectSubject {
    private ArrayList<ReconnectObserver> observers;
    public ReconnectObservable() {
        observers = new ArrayList<ReconnectObserver>();
    }
    @Override
    public void addObserver(ReconnectObserver observer) {
        observers.add(observer);
    }
    @Override
    public void notifyObservers(InternalMessageWs msg) {
        for(ReconnectObserver observer : observers) {
            observer.update(msg);
        }
    }
}
ReconnectSubject interface:
public interface ReconnectSubject {
    public void addObserver(ReconnectObserver observer);
    //public void notifyObservers();
    public void notifyObservers(InternalMessageWs msg);
}
InternalMessageWs class:
import javax.websocket.CloseReason;
import javax.websocket.Session;
public class InternalMessageWs {
    WsEventType type;
    Object event;
    InternalMessageWs(WsEventType type) {
        this.type = type;
        this.event = null;
    }
    InternalMessageWs(WsEventType type, Object event) {
        this.type = type;
        this.event=event;
    }
    public WsEventType getType() {
        return type;
    }
    public void setType(WsEventType type) {
        this.type = type;
    }
    public Object getEvent() {
        return event;
    }
    public void setEvent(Object event) {
        this.event = event;
    }
}
class OnOpenEvent {
    Session session;
    public OnOpenEvent(Session session) {
        this.session = session;
    }
    public Session getSession() {
        return session;
    }
    public void setSession(Session session) {
        this.session = session;
    }
}
class OnMessageEvent {
    Message message;
    Session session;
    public OnMessageEvent(Session session, Message message) {
        this.message = message;
        this.session = session;
    }
    public Message getMessage() {
        return message;
    }
    public void setMessage(Message message) {
        this.message = message;
    }
    public Session getSession() {
        return session;
    }
    public void setSession(Session session) {
        this.session = session;
    }
}
class OnCloseEvent {
    Session session;
    CloseReason reason;
    public OnCloseEvent(Session session, CloseReason reason) {
        this.session = session;
        this.reason = reason;
    }
    public Session getSession() {
        return session;
    }
    public void setSession(Session session) {
        this.session = session;
    }
    public CloseReason getReason() {
        return reason;
    }
    public void setReason(CloseReason reason) {
        this.reason = reason;
    }
}
class OnErrorEvent {
    Session session;
    Throwable t;
    public OnErrorEvent(Session session,Throwable t) {
        this.t = t;
        this.session=session;
    }
    public Throwable getT() {
        return t;
    }
    public void setT(Throwable t) {
        this.t = t;
    }
    public Session getSession() {
        return session;
    }
    public void setSession(Session session) {
        this.session = session;
    }
}
class OnConnectingEvent {
    String reason;
    public OnConnectingEvent(String reason) {
        this.reason = reason;
    }
    public String getReason() {
        return reason;
    }
    public void setReason(String reason) {
        this.reason = reason;
    }
}
enum WsEventType {
    ONOPEN,ONMESSAGE,ONCLOSE,ONERROR,
    ONCONNECTING            // Using in Reconnecting state of the Websocket client.
}
You need use Java 8 JDK because im usign callables, etc.