Build a Daily Coding Challenge Newsletter with Spring Boot

This guide walks you through creating a newsletter service using Spring Boot. This service will automatically send a daily email to subscribers, featuring a coding problem. The email will be dispatched every day at 7:30 PM.

Project Setup

First, we’ll lay the foundation for our Spring Boot application.

1. Create a Spring Boot Project

Begin by generating a new Spring Boot project. Include the following dependencies:

  • Spring Web: Provides the necessary components for building a REST API.
  • Spring Boot Mail: Enables email sending capabilities.
  • Spring Data JPA: Facilitates database interactions.
  • Spring Scheduler: Allows for scheduling tasks (like sending daily emails).
  • H2 Database (or MySQL): Choose H2 for in-memory development or MySQL for persistent data storage.

2. Configure Dependencies

Ensure your project’s pom.xml file includes the necessary dependencies. Here’s a snippet showing the essential dependencies:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

Database and Email Configuration

Next, configure your database connection and email settings.

3. Update application.properties

Modify your application.properties file with the appropriate database and email credentials. Below is an example configuration using H2 for the database and Gmail for email:

# H2 Database Configuration (for development)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# Email Configuration
spring.mail.host=smtp.gmail.com
spring.mail.port=587
[email protected]
spring.mail.password=your-email-password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

Important: For production environments, never hardcode sensitive information like your email password directly in application.properties. Instead, use environment variables or a dedicated secrets management solution.

Defining Data Models (Entities)

We’ll need to define the structure of our data using entities.

4. Create User Entity

Create a User entity to represent newsletter subscribers:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String email;
    private boolean subscribed;

    // Constructors, Getters, and Setters
    public User() {}

    public User(String email, boolean subscribed) {
        this.email = email;
        this.subscribed = subscribed;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public boolean isSubscribed() {
        return subscribed;
    }

    public void setSubscribed(boolean subscribed) {
        this.subscribed = subscribed;
    }    
}

5. Create Question Entity

Create a Question entity to store the coding challenge details:

@Entity
public class Question {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String url;
    private String difficulty;

    // Constructors, Getters and Setters

    public Question() {}

    public Question(String title, String url, String difficulty) {
        super();
        this.title = title;
        this.url = url;
        this.difficulty = difficulty;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDifficulty() {
        return difficulty;
    }

    public void setDifficulty(String difficulty) {
        this.difficulty = difficulty;
    }
}

Implementing Core Services

Now, let’s create the services to handle email sending and question retrieval.

6. Implement Email Service

The EmailService will be responsible for sending emails:

@Service
public class EmailService {
    @Autowired
    private JavaMailSender mailSender;

    public void sendEmail(String to, String subject, String text) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(to);
        message.setSubject(subject);
        message.setText(text);
        mailSender.send(message);
    }
}

7. Implement Question Service

The QuestionService will retrieve a random coding problem:

@Service
public class QuestionService {
    @Autowired
    private QuestionRepository questionRepository;

    public Question getRandomQuestion() {
        List<Question> questions = questionRepository.findAll();
        return questions.isEmpty() ? null : questions.get(new Random().nextInt(questions.size()));
    }
}

You also should create a QuestionRepository interface:

@Repository
public interface QuestionRepository extends JpaRepository<Question, Long> {
}

Managing Subscriptions

Create the components to handle user subscriptions and unsubscriptions.

8. Create User Repository

Create a UserRepository interface to interact with the User data:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

9. Create Subscription Controller

The SubscriptionController will expose endpoints for managing subscriptions:

@RestController
@RequestMapping("/api/subscription")
public class SubscriptionController {
    @Autowired
    private UserRepository userRepository;

    @PostMapping("/subscribe")
    public String subscribe(@RequestParam String email) {
        if (userRepository.findByEmail(email).isPresent()) {
            return "You are already subscribed!";
        }
        userRepository.save(new User(email, true));
        return "Subscription successful!";
    }

    @PostMapping("/unsubscribe")
    public String unsubscribe(@RequestParam String email) {
        userRepository.findByEmail(email).ifPresent(user -> {
            user.setSubscribed(false);
            userRepository.save(user);
        });
        return "Unsubscribed successfully!";
    }
}

Scheduling Daily Emails

Finally, we’ll implement the scheduler to send emails at the specified time.

10. Schedule Daily Emails

Create an EmailScheduler component to handle the scheduled task:

@Component
public class EmailScheduler {
    @Autowired
    private QuestionService questionService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private UserRepository userRepository;

    @Scheduled(cron = "0 30 19 * * ?") // Runs daily at 7:30 PM
    public void sendDailyQuestion() {
        Question question = questionService.getRandomQuestion();
        if (question != null) {
            String subject = "Daily Coding Challenge - " + question.getDifficulty();
            String body = "Today's challenge: " + question.getTitle() + "\n"
                        + "Solve it here: " + question.getUrl();

            List<User> subscribers = userRepository.findAll();
            for (User user : subscribers) {
                if (user.isSubscribed()) {
                    emailService.sendEmail(user.getEmail(), subject, body);
                }
            }
        }
    }
}

Running and Testing

  1. Run the Application: Start your Spring Boot application. You can typically do this from your IDE or by running mvn spring-boot:run in your terminal.

  2. Subscribe: Use a tool like curl (or a REST client like Postman) to subscribe an email address:

    curl -X POST "http://localhost:8080/api/subscription/[email protected]"
    
  3. Unsubscribe: Similarly, unsubscribe an email:
    curl -X POST "http://localhost:8080/api/subscription/[email protected]"
    
  4. Email Delivery: At 7:30 PM, check the inbox of the subscribed email address. You should receive the daily coding challenge.

You have now built a functional newsletter service that delivers daily coding problems to your subscribers!

Custom Newsletter Solutions by Innovative Software Technology

At Innovative Software Technology, we specialize in crafting custom software solutions, including sophisticated newsletter platforms. Looking to build a highly customized newsletter system with advanced features, user segmentation, detailed analytics, or complex scheduling? Our expertise in Spring Boot development, email marketing integration, database design, and API development allows us to build a tailored solution that precisely meets your requirements. We offer scalable newsletter software development, custom email template design, and automated email campaign management to help you engage your audience effectively. Contact us today to discuss your project and enhance your customer communication strategy with a robust and reliable newsletter service.

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.
You need to agree with the terms to proceed