In the view part, we have only two pages. One of them is the login page, to get the nickname of the user, and the second one is the main chat page to send messages to chat users.
As you can see in the controller section above, they are rendered by using two endpoints, /login and /chat. To create interactive pages, we will use some third-party JavaScript libraries. We will use them from CDN pages. You can see the login page below:
- <!DOCTYPE html>
- <html>
- <head lang="en">
- <meta charset="UTF-8"/>
- <title></title>
- <script src="//code.jquery.com/jquery-1.11.1.js"></script>
- <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
- <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
- <script>
- $(function(){
- if ($.cookie("realtime-chat-nickname")) {
- window.location = "/chat"
- } else {
- $("#frm-login").submit(function(event) {
- event.preventDefault();
- if ($("#nickname").val() !== '') {
- $.cookie("realtime-chat-nickname", $("#nickname").val());
- window.location = "/chat";
- }
- })
- }
- })
- </script>
- <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
- <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"/>
- </head>
- <body>
- <div class="container" style="padding-top: 50px">
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- <div class="login-panel panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">Choose a nickname to enter chat</h3>
- </div>
- <div class="panel-body">
- <form role="form" id="frm-login">
- <fieldset>
- <div class="form-group">
- <input class="form-control" placeholder="Enter Nickname" name="nickname" id="nickname" type="text" autofocus="" required=""/>
- </div>
- <button type="submit" class="btn btn-lg btn-success btn-block">Enter Chat</button>
- </fieldset>
- </form>
- </div>
- </div>
- </div>
- </div>
- </div>
- </body>
- </html>
Here's the chat page:
- <!DOCTYPE html>
- <html>
- <head lang="en">
- <meta charset="UTF-8"/>
- <title></title>
- <script src="//code.jquery.com/jquery-1.11.1.js"></script>
- <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
- <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
- <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.4.0/jquery.timeago.min.js"></script>
- <script src="//cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.0.0/sockjs.min.js"></script>
- <script src="//cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
- <script>
- var stompClient = null;
- function connect() {
- var socket = new SockJS('/newMessage');
- stompClient = Stomp.over(socket);
- stompClient.connect({}, function(frame) {
- stompClient.subscribe('/topic/newMessage', function(message){
- refreshMessages(JSON.parse(JSON.parse(message.body).content));
- });
- });
- }
- function disconnect() {
- if (stompClient != null) {
- stompClient.disconnect();
- }
- }
- function refreshMessages(messages) {
- $(".media-list").html("");
- $.each(messages.reverse(), function(i, message) {
- $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">'
- + message.text + '<br/><small class="text-muted">' + message.author + ' | ' + new Date(message.createDate) + '</small><hr/></div></div></div></li>');
- });
- }
- $(function(){
- if (typeof $.cookie("realtime-chat-nickname") === 'undefined') {
- window.location = "/login"
- } else {
- connect();
- $.get("/messages", function (messages) {
- refreshMessages(messages)
- });
- $("#sendMessage").on("click", function() {
- sendMessage()
- });
- $('#messageText').keyup(function(e){
- if(e.keyCode == 13)
- {
- sendMessage();
- }
- });
- }
- function sendMessage() {
- $container = $('.media-list');
- $container[0].scrollTop = $container[0].scrollHeight;
- var message = $("#messageText").val();
- var author = $.cookie("realtime-chat-nickname");
- stompClient.send("/app/newMessage", {}, JSON.stringify({ 'text': message, 'author': author}));
- $("#messageText").val("")
- $container.animate({ scrollTop: $container[0].scrollHeight }, "slow");
- }
- })
- </script>
- <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
- <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"/>
- <style type="text/css">
- .fixed-panel {
- min-height: 500px;
- max-height: 500px;
- }
- .media-list {
- overflow: auto;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="row " style="padding-top:40px;">
- <h3 class="text-center">Realtime Chat Application with Spring Boot, Websockets, and MongoDB </h3>
- <br/><br/>
- <div class="col-md-12">
- <div class="panel panel-info">
- <div class="panel-heading">
- <strong><span class="glyphicon glyphicon-list"></span> Chat History</strong>
- </div>
- <div class="panel-body fixed-panel">
- <ul class="media-list">
- </ul>
- </div>
- <div class="panel-footer">
- <div class="input-group">
- <input type="text" class="form-control" placeholder="Enter Message" id="messageText" autofocus=""/>
- <span class="input-group-btn">
- <button class="btn btn-info" type="button" id="sendMessage">SEND <span class="glyphicon glyphicon-send"></span></button>
- </span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </body>
- </html>
By the way, when you first open the chat page, the latest messages will be retrieved in the messages area. As you can see on the JavaScript side, our message channel is newMessage. So, we are listening to this channel, and when you click the Send button, the message in the text box will be sent to the endpoint and that message will be broadcast to the connected clients after successful storage.
As you can see, the software architecture here is very simple and easy to develop. We have production-ready code, and let's deploy it to Modulus.
Modulus is one of the best PaaS for deploying, scaling and monitoring your application in the language of your choice.
4. Deployment
4.1. Prerequisites
Before deploying the application, let's create a database by using the Modulus admin panel. You need a Modulus account for dba creation and application deployment, so please create an account if you don't have one.
Go to the Modulus dashboard and create a database:
![]() |
![]() |
To set the environment variables for MongoDB, you need to have an application. Go to Dashboard and click Projects. On this page, click Create New Project.
To continue with configuring the environment variables, please go to Dashboard and click Projects. Select your project, and click Administration. Scroll down the page, and set environment variables with the key SPRING_DATA_MONGODB_URI and value of your database URI:
![]() |
4.2. Deployment With CLI
In order to deploy the project, run a gradle build task:
- gradle build
- npm install -g modulus
- modulus login
- modulus deploy
- modulus project logs tail
5. Conclusion
The main purpose of this tutorial is to show you how to create a real-time chat application with Spring Boot, WebSockets, and MongoDB.
In order to run the project in production, Modulus is used as a PaaS provider. Modulus has very simple steps for deployment, and it also has an internal database (MongoDB) for our projects. Beside this, you can use very helpful tools in the Modulus dashboard like Logs, Notifications, Auto-Scaling, Db Administration, and more.
Written by Hüseyin Babal
If you found this post interesting, follow and support us.
Suggest for you:
Java Programming For Beginners
Complete Java For Selenium WebDriver And Test Automation
The Complete Android & Java Course - Build 21 Android Apps
Android Application Programming - Build 20+ Android Apps
Scalable programming with Scala and Spark
No comments:
Post a Comment