Java EE - Websockets

0

Witam, mam problem z Websocketem, po wprowadzeniu systemu pokoi nie chce sie polaczyc, mysle ze problem jest z przekazaniem parametru "roomID", nie widze tego jak kod sie wywoluje, da rade to jakos zdebugowac?

Najprawdopodobniej problem jest z przekazaniem parametru roomID.

Czy w funkcji OnOpen powinno byc w srodku (Session session, @PathParam "roomID" String roomID) ? nie rozumiem tego @PathParam, nie widze tego jak przekazuje ten parametr.

Mogłby ktos pomoc? Patrze na ten kod szukam w necie, ale nie moge do tego dojsc. Potrzebuje kogos madrego zeby spojrzal na ten kod i powiedzial mi co jest zle.

EchoServer.java

import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.ws.rs.PathParam;
 
@ServerEndpoint(value = "/echo/{roomID}") 
public class EchoServer {
  
    @OnOpen
    public void onOpen(Session session){
        String roomID = session.getUserProperties().get("roomID").toString();
        session.getUserProperties().put("roomID", roomID);
        SessionHandler.addSession(session, roomID);
        
        System.out.println(session.getId() + " has opened a connection"); 
        try {
            session.getBasicRemote().sendText("Connection Established");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
 
    @OnMessage
    public void onMessage(String message, Session session){
        System.out.println("Message from " + session.getId() + ": " + message);
        try {
            session.getBasicRemote().sendText(message);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session, String roomID){
        SessionHandler.removeSession(session, roomID);
        System.out.println("Session " +session.getId()+" has ended");
    }
}

SessionHandler.java

import java.util.HashMap;
import java.util.Map;
import javax.websocket.Session;

public class SessionHandler {
    private static final Map<String, Session> sessions = new HashMap<>();
    
    public static void addSession(Session session, String roomID){
        sessions.put(roomID, session);
    }
    
    public static void removeSession(Session session, String roomID){
        sessions.remove(roomID, session);
    }
    
    public static void sendToSession(Session session, String message){
          System.out.println("Message from " + session.getId() + ": " + message);
        try {
            session.getBasicRemote().sendText(message);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    public static void sendToAllConnectedSessionsInRoom(String roomID, String message){
        for (Map.Entry<String, Session> entry : sessions.entrySet()) {
            Session s = entry.getValue();
            if (s.isOpen() && s.getUserProperties().get("roomID").equals(roomID))
                try {
                    s.getBasicRemote().sendText(message);
                } catch (Exception ex) {
                ex.printStackTrace();
                }
        }
    }
}

index.html

<!DOCTYPE html>
 
<html>
    <head>
        <title>Echo Chamber</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
    </head>
    <body>
       
        <div>
            <input type="number" id="roomID"/>
            <input type="text" id="messageinput"/>
        </div>
        <div>
            <button type="button" onclick="openSocket();" >Open</button>
            <button type="button" onclick="send();" >Send</button>
            <button type="button" onclick="closeSocket();" >Close</button>
        </div>
        <!-- Server responses get written here -->
        <div id="messages"></div>
       
        <!-- Script to utilise the WebSocket -->
        <script type="text/javascript">
                       
            var webSocket;
            var messages = document.getElementById("messages");
           
           
            function openSocket(){
                if(webSocket !== undefined && webSocket.readyState !== WebSocket.CLOSED){
                   writeResponse("WebSocket is already opened.");
                    return;
                }
                webSocket = new WebSocket("ws://localhost:8080/EchoChamber/echo/{"+document.getElementById("roomID").value+"}");    
                 

                webSocket.onopen = function(event){
                    if(event.data === undefined)
                        return;
 
                    writeResponse(event.data);
                };
 
                webSocket.onmessage = function(event){
                    writeResponse(event.data);
                };
 
                webSocket.onclose = function(event){
                    writeResponse("Connection closed");
                };
            }
           
            function send(){
                var text = document.getElementById("messageinput").value;
                webSocket.send(text);
            }
           
            function closeSocket(){
                webSocket.close();
            }
 
            function writeResponse(text){
                messages.innerHTML += "<br/>" + text;
            }
           
        </script>
       
    </body>
</html>

enter image description here

0

https://www.baeldung.com/java-websockets

Prawie analogiczna aplikacja do Twojej. Masz przykład metody onOpen. Jak poszukasz troche to na gicie Baeldunga znajdziesz kod źródłowy każdego z artykułów.

0
kixe52 napisał(a):

https://www.baeldung.com/java-websockets

Prawie analogiczna aplikacja do Twojej. Masz przykład metody onOpen. Jak poszukasz troche to na gicie Baeldunga znajdziesz kod źródłowy każdego z artykułów.

Przeczytalem wszystko i nadal nie kumam o co chodzi, to @PathParam nigdzie nie opisuja. Nie mam pojecia co mam zle u siebie.

0

To jest metoda z Baeldunga.

 @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) throws IOException, EncodeException {

        this.session = session;
        chatEndpoints.add(this);
        users.put(session.getId(), username);

        Message message = new Message();
        message.setFrom(username);
        message.setContent("Connected!");
        broadcast(message);
    }

U siebie masz tylko

@ServerEndpoint(value = "/echo/{roomID}") 

Jeżeli chcesz potem wykorzystywać to 'roomId' to musisz przypisać temu jakąś wartość.
Po to jest właśnie to @PathParam("username") aby to co jest w Url przypisać do zmiennej.

edit:
Debugowałeś swój kod?

 String roomID = session.getUserProperties().get("roomID").toString();
 session.getUserProperties().put("roomID", roomID);
 SessionHandler.addSession(session, roomID);

Czy to Ci cokolwiek robi? roomId ma poprawną wartość? Bo wydaje mi się, że nie. Skąd wziąłeś ten kod?

0

Samemu pisalem, dobra to tak, roomID wpisuje przy probie polaczenia, czyli najpierw javascript w index.html

var room = document.getElementById("roomID").value;

i potem otwieram websocket

webSocket = new WebSocket("ws://localhost:8080/EchoChamber/echo/" + room);

Potem wchodzi do funkcji onOpen, czyli tutaj roomID powinno miec wartosc jaka wpisałem, czyli np 1 tak?

    @OnOpen
    public void onOpen(Session session, @PathParam ("roomID") String roomID){
        session.getUserProperties().put("roomID", roomID);
        SessionHandler.addSession(session, String.valueOf(session.getId()));
        
        System.out.println(session.getId() + " has opened a connection"); 
        try {
            session.getBasicRemote().sendText("Connection Established");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

Wlasnie nie wiem jak to zdebugowac, siedze w netbeansie...
Dzieki w ogole za pomoc, jestes jedyna osoba ktora mi pomaga

0

Może to Ci pomoże: https://netbeans.org/kb/docs/java/debug-visual.html

Ogólnie zasada jest taka, że stawiasz breakpoint w kodzie (linia, z które możesz mieć problem), uruchamiasz aplikacje w trybie Debug i wykonujesz flow usera. Jeśli wszystko pójdzie dobrze to wejdzie do tej metody co chcesz. Tam możesz podejrzeć min jaką wartość ma konkretna zmienna.

Upewnij się jeszcze czy z poziomu JSa też jest wszystko ok. Np czy

var room = document.getElementById("roomID").value;

trzyma dokładnie to co chcesz.

0
kixe52 napisał(a):

Może to Ci pomoże: https://netbeans.org/kb/docs/java/debug-visual.html

Ogólnie zasada jest taka, że stawiasz breakpoint w kodzie (linia, z które możesz mieć problem), uruchamiasz aplikacje w trybie Debug i wykonujesz flow usera. Jeśli wszystko pójdzie dobrze to wejdzie do tej metody co chcesz. Tam możesz podejrzeć min jaką wartość ma konkretna zmienna.

Upewnij się jeszcze czy z poziomu JSa też jest wszystko ok. Np czy

var room = document.getElementById("roomID").value;

trzyma dokładnie to co chcesz.

Czyli teoretycznie jakby trzymalo to co chce, np 1.
To potem w funkcji onOpen(Session session, @PathParam ("roomID") String roomID)
to od razu wchodzi mi 1 zamiast roomID?

0

Teoretycznie jeśli wcześniej jest ok to wchodzi Ci do metody z 2 argumentami, gdzie jednym z nich jest argument o nazwie roomID z wartością 1.

0
kixe52 napisał(a):

Teoretycznie jeśli wcześniej jest ok to wchodzi Ci do metody z 2 argumentami, gdzie jednym z nich jest argument o nazwie roomID z wartością 1.

Czyli w takim razie cos zle musi byc w index.html najprawdopodobniej.

Zrobilem breakpointa w index.html ale debuger sie nie zatrzymuje, nie moge wybrac opcji przejdz dalej

Mozesz mi powiedziec czym sie rozni

@ServerEndpoint("/echo/{roomID}") 

od

@ServerEndpoint(value = "/echo/{roomID}") 

1

Nie pracowałem z Netbeansem i nie wiem czy może debugowac JS. JS ogólnie możesz debugować w swojej przeglądarce. A jeśli tego nie ogarniasz (naucz się) to dodaj printowanie na console przeglądarkową roomID i Twojego obiektu webSocket .

Także jeśli zrobisz to co powyżej i będzie ok, to postaraj się zdebugowac kod JAVY. Tzn stawiasz breakpoint przy kodzie javowym a nie JSowym ;)

0
kixe52 napisał(a):

Nie pracowałem z Netbeansem i nie wiem czy może debugowac JS. JS ogólnie możesz debugować w swojej przeglądarce. A jeśli tego nie ogarniasz (naucz się) to dodaj printowanie na console przeglądarkową roomID i Twojego obiektu webSocket .

Także jeśli zrobisz to co powyżej i będzie ok, to postaraj się zdebugowac kod JAVY. Tzn stawiasz breakpoint przy kodzie javowym a nie JSowym ;)

Dobra bede kombinowal, dam znac jak progres dziekuje za pomoc

1
simonsoft napisał(a):

Mozesz mi powiedziec czym sie rozni

@ServerEndpoint("/echo/{roomID}") 

od

@ServerEndpoint(value = "/echo/{roomID}") 

Nie powinno być większych różnic. Zgodnie z https://docs.oracle.com/javaee/7/api/javax/websocket/server/ServerEndpoint.html
używa się wersji bez value, ale skoro ktoś z taką renomą jak Baeldung wrzuca drugą wersję tzn, że powinna być ok. Dla pewności spróbuj tą bez value.

edit: wydaje mi się, że w sytuacji gdy wrzucasz więcej niż 1 argument, musisz oznaczyć co jest czym. Oficjalna dokumentacja mówi, że możesz wrzucić też tam decoder/encoder. Wtedy dodajesz to value= oraz encoders= itp.
Gdy używasz tylko z 1 argumentem, tym wymaganym, to obie wersje są ok, z/bez 'value'.

0
kixe52 napisał(a):
simonsoft napisał(a):

Mozesz mi powiedziec czym sie rozni

@ServerEndpoint("/echo/{roomID}") 

od

@ServerEndpoint(value = "/echo/{roomID}") 

Nie powinno być większych różnic. Zgodnie z https://docs.oracle.com/javaee/7/api/javax/websocket/server/ServerEndpoint.html
używa się wersji bez value, ale skoro ktoś z taką renomą jak Baeldung wrzuca drugą wersję tzn, że powinna być ok. Dla pewności spróbuj tą bez value.

edit: wydaje mi się, że w sytuacji gdy wrzucasz więcej niż 1 argument, musisz oznaczyć co jest czym. Oficjalna dokumentacja mówi, że możesz wrzucić też tam decoder/encoder. Wtedy dodajesz to value= oraz encoders= itp.
Gdy używasz tylko z 1 argumentem, tym wymaganym, to obie wersje są ok, z/bez 'value'.

Okay, zdebugowalem i

var room = document.getElementById("roomID").value;

nie przyjmuje zadnej wartosci, jest puste. Czy powinienem dodac method="get" albo "post" jako akcja do <input type="number" id="roomID" />?

0

Okay, wrzucilem

var room = document.getElementById("roomID").value;

do funkcji function
openSocket()
i daje 1 wiec jest okay, ale handshake nadal unsuccesful

screenshot-20200415143138.png

0

Dobra ludzie dziala !!!!!! Wszystko przez metode

onClose(Session session, String roomID)

na

onClose(Session session)

String roomID, nie pasowalo do metody i dlatego nie laczyl sie, nie wazne ze nigdy tej metody nie uzywal, ale wazne ze ona nie pasowala do domyslnej metody onClose(Session session) za duzo parametrow.
Dziekuje za pomoc !

1 użytkowników online, w tym zalogowanych: 0, gości: 1