How to add chat into a Spring Boot App

How to add chat into a Spring Boot App

·

5 min read

In today’s article, we will be taking a slightly different direction than our previous ones. We will not be theming a TalkJS chat but integrating it with a Spring Boot application to retrieve user data. For the implementation, we will model an agent and a bunch of customers. This data will then be retrieved using a REST API from the Spring Boot application. For the sake of simplicity, we will use the in-memory H2 database, but you can expand it to other popular database options. You can find the entire source code for this project on GitHub.

Note

This tutorial does not implement Spring Security for authentication and authorization. Still, in a production scenario, the users must register themselves, and the passwords must be stored in a hashed format. Only authenticated users must be allowed to start the chat with the agent. On the other hand, the agents must authenticate themselves before attending to a customer as well.

Setting up the Spring Boot Application

To set up the Spring Boot application, the easiest way is to have Spring Tool Suite. You can install it from here. Launch the application and create a new Spring Starter project. The wizard will ask for a name and all the dependencies that you want to add. For this application, we need the following:

  • Spring Data JPA
  • Spring Web
  • H2 Database

Spring Starter project

Once you click Finish, it will set up a Spring Boot application that is ready to run. Open, application.properties present inside src/main/resources. Add the following lines to set up the H2 in-memory database.

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto= update
spring.h2.console.enabled=true

This will configure the H2 database and also enable the console to visually view and manage the data present inside the database.

Creating the Model and Repository

We will now model the user and create a repository to save and retrieve users. Spring Boot provides an easy-to-use interface JpaRepository, that already has most of the methods we need. The model class is shown below. We use the @Entity annotation to mark the class as an entity that will be present in a database. The @Table annotation denotes the name of the table.

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name = "dp")
    private String dp;
    @Column(name = "email")
    private String email;
    @Column(name = "role")
    private String role;
}

There are five fields for the user. The id is automatically generated by Hibernate which is used within Spring Boot for Object-Relational Mapping (ORM). The @Column annotation denotes each column's name within the database. We also have a constructor, getters, and setters for the above class, but it is not shown above since they are auto-generated.

The repository interface is by far the smallest in the project. We just need to have an empty interface that implements the JpaRepository. This lets us use all the methods that come with it.

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

Creating the Controller

Since this is a web application consisting of APIs, we need to create a controller. We have two endpoints. One is/createUser and the other is /getUser. The following code outlines the controller.

@CrossOrigin("*")
@RestController
public class UserController {

    @Autowired
    UserRepository userRepository;

    @PostMapping(value = "/createUser")
    public ResponseEntity<User> createUser(@RequestBody User user) {
    return new ResponseEntity<>(userRepository.save(user), HttpStatus.OK);
    }

    @GetMapping(value = "/getUser")
    public ResponseEntity<User> getUser(@RequestParam(required = true) Long userId) {
    return new ResponseEntity<>(userRepository.findById(userId).get(), HttpStatus.OK);
    }

}

The @Autowired annotation is used for dependency injection. We have the @GetMapping annotation to denote a GET request and a @PostMappingannotation to denote a POST request. To create a user, we use the save() method present inside the userRepository. Note that we don't check for errors here since there is no scope for variability here. All the data is pre-defined. In a production scenario, you must ensure that there are proper error checks. The @CrossOrigins annotation is present because we are making API calls within the localhost.

Creating users using the API and verifying them

Use the following payload to create an agent and a user. The application will be running on localhost:8080. You can use Postman to perform the API calls.

URL: localhost:8080/createUser TYPE: POST

{
    "name":"Tom Hardy",
    "dp": "https://randomuser.me/api/portraits/men/1.jpg",
    "email":"tom.hardy@operator.com",
    "role":"AGENT"
}
{
    "name":"John Morrison",
    "dp": "https://randomuser.me/api/portraits/men/62.jpg",
    "email":"john.morrison@operator.com",
    "role":"USER"
}

You should get a 200 OK response and the created user for both the API calls. Since we enabled the H2 console, we can also view the database contents at localhost:8080/h2-console.

database console

Setting up the TalkJS application

Set up a TalkJS Inbox using our Getting Started Guide. In the script file, make changes to the code as follows.

(
    async function() {
    await Talk.ready;
    let agent = await getAgent();
    let user = await getUser();

    const session = new Talk.Session({
        appId: 'YOUR_APP_ID_HERE',
        me: user,
    });
    var conversation = session.getOrCreateConversation(Talk.oneOnOneId(user, agent));

    conversation.setAttributes({
        welcomeMessages: ["You can start typing your message here and one of our agents will be with you shortly.", "Please do not divulge any of your personal information."]
    })
    conversation.setParticipant(user);
    conversation.setParticipant(agent);

    var inbox = session.createInbox(conversation);
    inbox.mount(document.getElementById("talkjs-container"));
}());

Note that we use two asynchronous functions here, getAgent() and getUser() to retrieve the agent and user data. Add the following functions above the existing code inside the script file.

const getAgent = async () => {
    const response = await fetch('http://localhost:8080/getUser?userId=1');
    const data = await response.json();
    let agent = new Talk.User({
        id: data.id,
        name: data.name,
        photoUrl: data.dp,
        email: data.email,
        role: data.role
    });
    return agent;
}
const getUser = async () => {
    const response = await fetch('http://localhost:8080/getUser?userId=2');
    const data = await response.json();
    let user = new Talk.User({
        id: data.id,
        name: data.name,
        photoUrl: data.dp,
        email: data.email,
        role: data.role
    });
    return user;
}

Once we receive the user and agent data from our database through the API calls, we create Talk.User objects and map them to it. This will allow us to start a conversation with the users retrieved from the database.

Conclusion

final talkjs chatbox

We have successfully integrated a Spring Boot application with TalkJS and retrieved user data from an in-memory database through API calls. Even though this is a very simple example that showcases the capabilities of TalkJS, you can expand it to any production scenario by implementing authentication, authorization, role-based dashboards, and more. The entire source code for this project is available on GitHub.