├── .color
├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
└── java
└── sample
├── Application.java
├── ClientMessage.java
└── ServerMessage.java
/.color:
--------------------------------------------------------------------------------
1 | #402D2B
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 jaysridhar
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spring WebSocket Chat Client
2 |
3 | A sample implementation demonstrating usage of Spring WebSockets for
4 | the client. For a compatible server implementation, see
5 | [https://github.com/jaysridhar/spring-websocket-server]. The server
6 | includes a web-based client (HTML/JS), however this client
7 | demonstrates usage of WebSockets from Java in the Spring context.
8 |
9 | Build the project using:
10 |
11 | mvn clean package
12 |
13 | And run it as follows:
14 |
15 | java -jar target/chat-client-0.1.0.jar
16 |
17 | The client connects to the server on the localhost at port 9090, send
18 | a starting message and shows a prompt on the console which can be used
19 | to send further messages. Any messages sent to the server (maybe from
20 | a second console or the web client) is also received and echoed on the
21 | console.
22 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | sample
8 | chat-client
9 | 0.1.0
10 |
11 |
12 | org.springframework.boot
13 | spring-boot-starter-parent
14 | 1.4.3.RELEASE
15 |
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-websocket
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter
29 |
30 |
31 | org.springframework
32 | spring-messaging
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-maven-plugin
41 |
42 |
43 | maven-clean-plugin
44 | 2.5
45 |
46 |
47 |
48 | .
49 |
50 | **/*~
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/src/main/java/sample/Application.java:
--------------------------------------------------------------------------------
1 | package sample;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 |
6 | import java.util.List;
7 | import java.util.ArrayList;
8 | import java.util.Map;
9 | import java.util.HashMap;
10 |
11 | import java.util.concurrent.ThreadLocalRandom;
12 |
13 | import java.lang.reflect.Type;
14 |
15 | import org.springframework.web.socket.client.WebSocketConnectionManager;
16 | import org.springframework.web.socket.client.WebSocketClient;
17 | import org.springframework.web.socket.client.standard.StandardWebSocketClient;
18 | import org.springframework.web.socket.sockjs.client.WebSocketTransport;
19 | import org.springframework.web.socket.sockjs.client.Transport;
20 | import org.springframework.web.socket.sockjs.client.SockJsClient;
21 | import org.springframework.web.socket.sockjs.frame.Jackson2SockJsMessageCodec;
22 | import org.springframework.messaging.converter.StringMessageConverter;
23 | import org.springframework.messaging.converter.MappingJackson2MessageConverter;
24 | import org.springframework.web.socket.messaging.WebSocketStompClient;
25 |
26 | import org.springframework.messaging.simp.stomp.StompSessionHandler;
27 | import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
28 | import org.springframework.messaging.simp.stomp.StompSession;
29 | import org.springframework.messaging.simp.stomp.StompHeaders;
30 | import org.springframework.messaging.simp.stomp.StompFrameHandler;
31 |
32 | import com.fasterxml.jackson.databind.ObjectMapper;
33 |
34 | /*
35 | * WebSocket client application. Performs client side setup and sends
36 | * messages.
37 | *
38 | * @Author Jay Sridhar
39 | */
40 | public class Application
41 | {
42 | static public class MyStompSessionHandler
43 | extends StompSessionHandlerAdapter
44 | {
45 | private String userId;
46 |
47 | public MyStompSessionHandler(String userId)
48 | {
49 | this.userId = userId;
50 | }
51 |
52 | private void showHeaders(StompHeaders headers)
53 | {
54 | for (Map.Entry> e:headers.entrySet()) {
55 | System.err.print(" " + e.getKey() + ": ");
56 | boolean first = true;
57 | for (String v : e.getValue()) {
58 | if ( ! first ) System.err.print(", ");
59 | System.err.print(v);
60 | first = false;
61 | }
62 | System.err.println();
63 | }
64 | }
65 |
66 | private void sendJsonMessage(StompSession session)
67 | {
68 | ClientMessage msg = new ClientMessage(userId,
69 | "hello from spring");
70 | session.send("/app/chat/java", msg);
71 | }
72 |
73 | private void subscribeTopic(String topic,StompSession session)
74 | {
75 | session.subscribe(topic, new StompFrameHandler() {
76 |
77 | @Override
78 | public Type getPayloadType(StompHeaders headers) {
79 | return ServerMessage.class;
80 | }
81 |
82 | @Override
83 | public void handleFrame(StompHeaders headers,
84 | Object payload)
85 | {
86 | System.err.println(payload.toString());
87 | }
88 | });
89 | }
90 |
91 | @Override
92 | public void afterConnected(StompSession session,
93 | StompHeaders connectedHeaders)
94 | {
95 | System.err.println("Connected! Headers:");
96 | showHeaders(connectedHeaders);
97 |
98 | subscribeTopic("/topic/messages", session);
99 | sendJsonMessage(session);
100 | }
101 | }
102 |
103 | public static void main(String args[]) throws Exception
104 | {
105 | WebSocketClient simpleWebSocketClient =
106 | new StandardWebSocketClient();
107 | List transports = new ArrayList<>(1);
108 | transports.add(new WebSocketTransport(simpleWebSocketClient));
109 |
110 | SockJsClient sockJsClient = new SockJsClient(transports);
111 | WebSocketStompClient stompClient =
112 | new WebSocketStompClient(sockJsClient);
113 | stompClient.setMessageConverter(new MappingJackson2MessageConverter());
114 |
115 | String url = "ws://localhost:9090/chat";
116 | String userId = "spring-" +
117 | ThreadLocalRandom.current().nextInt(1, 99);
118 | StompSessionHandler sessionHandler = new MyStompSessionHandler(userId);
119 | StompSession session = stompClient.connect(url, sessionHandler)
120 | .get();
121 | BufferedReader in =
122 | new BufferedReader(new InputStreamReader(System.in));
123 | for (;;) {
124 | System.out.print(userId + " >> ");
125 | System.out.flush();
126 | String line = in.readLine();
127 | if ( line == null ) break;
128 | if ( line.length() == 0 ) continue;
129 | ClientMessage msg = new ClientMessage(userId, line);
130 | session.send("/app/chat/java", msg);
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/main/java/sample/ClientMessage.java:
--------------------------------------------------------------------------------
1 | package sample;
2 |
3 | /*
4 | * Message sent to server.
5 | *
6 | * @Author Jay Sridhar
7 | */
8 | public class ClientMessage
9 | {
10 | private String from;
11 | private String text;
12 |
13 | public ClientMessage() {}
14 |
15 | public ClientMessage(String from,String text)
16 | {
17 | this.from = from;
18 | this.text = text;
19 | }
20 |
21 | public String getFrom()
22 | {
23 | return from;
24 | }
25 |
26 | public void setFrom(String from)
27 | {
28 | this.from = from;
29 | }
30 |
31 | public String getText()
32 | {
33 | return text;
34 | }
35 |
36 | public void setText(String text)
37 | {
38 | this.text = text;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/sample/ServerMessage.java:
--------------------------------------------------------------------------------
1 | package sample;
2 |
3 | import java.util.Date;
4 |
5 | /*
6 | * Message received from server.
7 | *
8 | * @Author Jay Sridhar
9 | */
10 | public class ServerMessage
11 | {
12 | private String from;
13 | private String message;
14 | private String topic;
15 | private Date time = new Date();
16 |
17 | public ServerMessage() {}
18 |
19 | public ServerMessage(String from,String message,String topic)
20 | {
21 | this.from = from;
22 | this.message = message;
23 | this.topic = topic;
24 | }
25 |
26 | public String getFrom()
27 | {
28 | return from;
29 | }
30 |
31 | public void setFrom(String from)
32 | {
33 | this.from = from;
34 | }
35 |
36 | public String getMessage()
37 | {
38 | return message;
39 | }
40 |
41 | public void setMessage(String message)
42 | {
43 | this.message = message;
44 | }
45 |
46 | public String getTopic()
47 | {
48 | return topic;
49 | }
50 |
51 | public void setTopic(String topic)
52 | {
53 | this.topic = topic;
54 | }
55 |
56 | public Date getTime()
57 | {
58 | return time;
59 | }
60 |
61 | public String toString()
62 | {
63 | return String
64 | .format("{from: %1$-10s | topic: %2$-10s | time: %4$-15d | mesg: %3$s}",
65 | getFrom(), getTopic(),
66 | getMessage(), getTime().getTime());
67 | }
68 | }
69 |
--------------------------------------------------------------------------------