Group scheduling – Control your events participation with Java

Group scheduling – Control your events participation with Java

11 min read

You have created an event, but there is limited capacity. You want people to sign up but you don’t want anyone to show up just to realize the event is already fully booked. Group scheduling is the perfect way to control your event participation and using the Nylas Java SDK makes it possible.

You will need just to create an event, specify its capacity and let participants know how many spots are left for them to join.

Is your system ready?

If you already have the Nylas Java SDK installed and your Java environment is configured, then continue along with the blog.

Otherwise, I would recommend that you read the post How to Send Emails with the Nylas Java SDK where the basic setup is clearly explained.

What are we going to talk about?

What our application will look like

Before going any further, let’s see what our application will look like:

Group scheduling with available spots

We have the title, date and time of the event. Also, we have the number of available spots and we can enter our name and email address.

Group scheduling adding a participant

When we press submit, we’re going to get registered and receive a confirmation message:

Participant confirmation

Also, we will receive an invitation in our mailbox:

Event invitation sent

When registering, it’s important to fill out all fields:

Registration validation
All fields are required

When all available spots are taken, registration will fail:

Group scheduling with no more available spots

With a confirmation message:

Confirmation of no available spots

Creating a Java event generator

As we need an event where people can register, let’s create a project called EventGenerator. We need to create a folder called EventGenerator and modify the pom.xml file like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>EventGenerator</groupId>
   <artifactId>EventGenerator</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <maven.compiler.source>17</maven.compiler.source>
       <maven.compiler.target>17</maven.compiler.target>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-simple</artifactId>
           <version>1.7.25</version>
       </dependency>
       <dependency>
           <groupId>io.github.cdimascio</groupId>
           <artifactId>dotenv-java</artifactId>
           <version>2.2.4</version>
       </dependency>
       <dependency>
           <groupId>com.nylas.sdk</groupId>
           <artifactId>nylas-java-sdk</artifactId>
           <version>1.18.0</version>
       </dependency>
   </dependencies>

   <build>
       <pluginManagement>
           <plugins>
               <plugin>
                   <groupId>org.codehaus.mojo</groupId>
                   <artifactId>exec-maven-plugin</artifactId>
                   <version>1.2.1</version>
                   <executions>
                       <execution>
                           <phase>package</phase>
                           <goals>
                               <goal>java</goal>
                           </goals>
                       </execution>
                   </executions>
                   <configuration>
                       <mainClass>EventGenerator</mainClass>
                       <cleanupDaemonThreads>false</cleanupDaemonThreads>
                   </configuration>
               </plugin>
           </plugins>
       </pluginManagement>
   </build>

</project>

Then create a class called EventGenerator.java:

//Import Java Utilities
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;

// Import Nylas Packages
import com.nylas.RequestFailedException;
import com.nylas.NylasAccount;
import com.nylas.NylasClient;
import com.nylas.Event;
import com.nylas.Participant;

//Import DotEnv to handle .env files
import io.github.cdimascio.dotenv.Dotenv;
import io.github.cdimascio.dotenv.DotenvException;

public class EventGenerator {
   public static void main(String[] args) throws RequestFailedException, IOException {
       Dotenv dotenv = Dotenv.load();
       // Create the client object
       NylasClient client = new NylasClient();
       // Connect it to Nylas using the Access Token from the .env file
       NylasAccount account = client.account(dotenv.get("ACCESS_TOKEN"));

       // Get today's date
       LocalDate today = LocalDate.now();
       // Set time. As we're using UTC we need to add the hours
       // in difference
       // from our own Timezone
       Instant sixPmUtc = today.atTime(16, 0).toInstant(ZoneOffset.UTC);
       // Set the date and time for the event.
       // We add 30 minutes to the starting time
       Event event = new Event(dotenv.get("CALENDAR_ID"),
                     new Event.Timespan(sixPmUtc,
                     sixPmUtc.plus(30, ChronoUnit.MINUTES)));
       // Set Title, Location and Description
       event.setTitle("Zumba Class with Nyla");
       event.setLocation("Nylas' Office");
       event.setCapacity(3);

       Event event_created = account.events().create(event, true);
       if(event_created.getId() != null){
           System.out.println("Event created successfully");
           System.out.println(“Id: “ + event_created.getId());
       }else{
           System.out.println("There was an error creating the event");
       }
   }
}

In order to run our application, we need to compile it by typing the following on the terminal window:

$ mvn package
Compiling our Event Generator

To actually run the application, we need to type the following:

$ mvn exec:java -Dexec.mainClass="EventGenerator"
Running our Event Generator

Creating the Java Group Scheduling Project

First, we’re going to create a folder called GroupScheduling that will include a folder called resources. Inside resources, we need to create a folder called templates and another folder called public. Inside the public folder, we need to create a new folder called images.

On the images folder, we will have this image:

Nyla being cool

We want to use a web framework, and a very light and fast option is Spark. For the template engine, Mustache is more than enough.

Now, let’s create our pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>GroupScheduling</groupId>
   <artifactId>GroupScheduling</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <maven.compiler.source>17</maven.compiler.source>
       <maven.compiler.target>17</maven.compiler.target>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-simple</artifactId>
           <version>1.7.25</version>
       </dependency>
       <dependency>
           <groupId>com.sparkjava</groupId>
           <artifactId>spark-core</artifactId>
           <version>2.9.4</version>
       </dependency>
       <dependency>
           <groupId>io.github.cdimascio</groupId>
           <artifactId>dotenv-java</artifactId>
           <version>2.2.4</version>
       </dependency>
       <dependency>
           <groupId>com.sparkjava</groupId>
           <artifactId>spark-template-mustache</artifactId>
           <version>2.7.1</version>
       </dependency>
       <dependency>
           <groupId>com.nylas.sdk</groupId>
           <artifactId>nylas-java-sdk</artifactId>
           <version>1.18.0</version>
       </dependency>
   </dependencies>

</project>

Our main class will be called GroupScheduling.java:

// Import Java Utilities
import java.io.IOException;
import java.lang.Exception;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.time.temporal.ChronoUnit;

// Import Spark and Mustache libraries
import spark.ModelAndView;
import static spark.Spark.*;
import spark.template.mustache.MustacheTemplateEngine;

//Import Nylas Packages
import com.nylas.RequestFailedException;
import com.nylas.NylasAccount;
import com.nylas.NylasClient;
import com.nylas.Event;
import com.nylas.Participant;

//Import DotEnv to handle .env files
import io.github.cdimascio.dotenv.Dotenv;

public class GroupScheduling {
   public static void main(String[] args) throws RequestFailedException, IOException {
       staticFiles.location("/public");
       // Load the .env file
       Dotenv dotenv = Dotenv.load();
       // Create the client object
       NylasClient client = new NylasClient();
       // Connect it to Nylas using the Access Token from the .env file
       NylasAccount account = client.account(dotenv.get("ACCESS_TOKEN"));
       // Get an event using its Id
       Event event = account.events().get(dotenv.get("EVENT_ID"));
       // Read the event details
       String title = event.getTitle();
       Event.Timespan _day = (Event.Timespan) event.getWhen();
       LocalDateTime ldt = LocalDateTime.ofInstant(_day.getStartTime(), ZoneOffset.UTC);
       LocalDateTime ldt_to = LocalDateTime.ofInstant(_day.getEndTime(), ZoneOffset.UTC);
       String day_name = ldt.getDayOfWeek().toString().toLowerCase();
       String day = day_name.substring(0, 1).toUpperCase() + day_name.substring(1) + " " + ldt.getDayOfMonth() + ", " + ldt.getYear();
       DateFormat dateFormat = new SimpleDateFormat("hh:mm aa");
       Date _from_date = Date.from(ldt.minus(5, ChronoUnit.HOURS).atZone(ZoneId.systemDefault()).toInstant());
       Date _to_date = Date.from(ldt_to.minus(5, ChronoUnit.HOURS).atZone(ZoneId.systemDefault()).toInstant());
       String _from = dateFormat.format(_from_date).toString().toUpperCase();
       String _to = dateFormat.format(_to_date).toString().toUpperCase();

       // Default path when we load our web application
       get("/", (request, response) -> {
           // Update capacity
           Integer capacity = event.getCapacity() - event.getParticipants().size();
           if (capacity < 0){
               capacity = 0;
           }
           // Create a model to pass information to the mustache template
           Map<String, Object> model = new HashMap<>();
           model.put("title", title);
           model.put("day", day);
           model.put("_from", _from);
           model.put("_to", _to);
           model.put("capacity", capacity.toString());
           model.put("name", "");
           model.put("email", "");

           // Call the mustache template
           return new ModelAndView(model, "main.mustache");
       }, new MustacheTemplateEngine());

       // When we submit the form, we're posting data
       post("/", (request, response) -> {
           // Grab the form fields
           String name = request.queryParams("name");
           String email = request.queryParams("email");
           String message = "";
           String explanation = "";
           // Validate that they are all filled
           // Otherwise halt execution and display an error message
           if(name.equals("") || email.equals("")){
               String halt_msg = "<html>\n" +
                       "<head>\n" +
                       "    <script src=\"https://cdn.tailwindcss.com\"></script>\n" +
                       "    <title>Zumba Class with Nyla</title>\n" +
                       "</head>\n" +
                       "<body>\n" +
                       "<div class=\"bg-red-300 border-green-600 border-b p-4 m-4 rounded grid place-items-center\">\n" +
                       "<p class=\"font-semibold\">You must specify all fields</p>\n" +
                       "</div>\n" +
                       "</body>\n" +
                       "</html>";
               halt(halt_msg);
           }
           // Create an array of participants
           ArrayList<Participant> participants = new ArrayList<Participant>();
           // Add existing participants
           for(Participant participant : event.getParticipants()){
               participants.add(new Participant(participant.getEmail()).name(participant.getName()));
           }
           // Add new participant
           participants.add(new Participant(email).name(name));
           // Set the participants list
           event.setParticipants(participants);
           try{
               // Update the event
               account.events().update(event, true);
               message = "Thanks " + name + " - " + email;
               explanation = "You have successfully registered for " + title;
           } catch(Exception e){
               message = "Sorry " + name + " - " + email;
               explanation = "Sadly, there's not space left for you to join " + title;
           } finally {
               // Create a model to pass information to the mustache template
               Map<String, Object> model = new HashMap<>();
               model.put("message", message);
               model.put("explanation", explanation);
               return new ModelAndView(model, "confirmation.mustache");
           }
       }, new MustacheTemplateEngine());
   }
}

We’re going to need two mustache template files, main.mustache and confirmation.mustache:

Let’s start with main.mustache:

<html>
<head>
   <script src="https://cdn.tailwindcss.com"></script>
   <title>Zumba Class with Nyla</title>
</head>
<body>
<div class="bg-[#315acb] border-green-600 border-b p-4 m-4 rounded grid place-items-center">
   <p class="text-6xl text-center">{{title}}</p><br>
   <p class="text-4xl text-center">{{day}}</p><br>
   <p class="text-4xl text-center">from {{_from}} to {{_to}}</p><br>
   <img src="images/Nyla.png">
   <br>
   <p class="text-2xl text-center">Currently we have <b>{{capacity}}</b> available spots.</p>
   <br>
   <form method="post">
       <label for="name"><b>Name</b></label>
       <input type="text" name="name"
              placeholder="Your name"
              value="{{name}}"></input>
       <br><br>
       <label for="email"><b>Email</b></label>
       <input type="email" name="email"
              placeholder="Your email"
              value="{{email}}"></input>
       <br><br>
       <button type="submit" class="block bg-blue-500 hover:bg-blue-700 text-white text-lg mx-auto py-2 px-4 rounded-full">Submit</button>
   </form>
</div>
</body>
</html>

And then confirmation.mustache:

<html>
<head>
   <script src="https://cdn.tailwindcss.com"></script>
   <title>Zumba Class with Nyla</title>
</head>
<body>
<div class="bg-[#315acb] border-green-600 border-b p-4 m-4 rounded grid place-items-center">
   <h1 class="text-3xl">{{message}}</h1>
   <p class="font-semibold">{{explanation}}</p>
   <p class="font-semibold">You can now go <a href="/" class="text-green-600">back</a></p>
</div>
</body>
</html>

Running the Java Group Scheduling application

In order to run our application, we need to compile it by typing the following on the terminal window:

$ mvn package
Compiling our Group Scheduling application

To run our Group Scheduling application using Java, we need to type the following:

$ mvn exec:java -Dexec.mainClass="GroupScheduling"
Running our Group Scheduling application

Our application will be running on port 4567 of localhost, so we just need to open our favourite browser and go to the following address:

http://localhost:4567

If you want to learn more about our Calendar APIs, please go to our documentation Calendar API Overview.

You can sign up Nylas for free and start building!

Related resources

How to build a CRM in 3 sprints with Nylas

What is a CRM? CRM stands for Customer Relationship Management, and it’s basically a way…

How to create an appointment scheduler in your React app

Learn how to create an appointment scheduler in your React app using Nylas Scheduler. Streamline bookings and UX with step-by-step guidance.

Beyond APIs: Designing elegant, smart Web Components

Dive into the world of smart Web Components for advanced API integration solutions. Design elegant, customizable elements to elevate user experiences.