I just announced the newSpring Security 5 modules (primarily focused on OAuth2) in the course:

>> CHECK OUT LEARN SPRING SECURITY

1. Overview

In this tutorial – we’re continuing the ongoing Registration with Spring Security series to setup a scheduled task to purge expired VerificationTokens. During the registration process a VerificationToken is persisted. In this article we will show how to remove these entities.

2. Removing An Expired Token

Recall from the prior article in the series that a verification token has the member expiryDate, representing the expiration timestamp for the token:

@Entity
public class VerificationToken {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String token;

    @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "user_id", 
      foreignKey = @ForeignKey(name="FK_VERIFY_USER"))
    private User user;

    private Date expiryDate;
    ...
}

We’ll use this expiryDate property to generate a query with Spring Data.

If you’re looking for more info on Spring Data JPA, have a look at this article.

2.1. The Delete Operation

To facilitate the token removal we’ll add a new method to our VerificationTokenRepository for deleting expired tokens:

public interface VerificationTokenRepository
  extends JpaRepository<VerificationToken, Long> {

    void deleteByExpiryDateLessThan(Date now);
}

The use of the query keyword LessThan indicates to Spring Data’s query creation mechanism that we are only interested in tokens whose expiryDate property is less than the specified time.

Note that because VerificationToken has a @OneToOne association with User marked with FetchType.EAGER, a select is also issued to populate the User entity— even though the signature of deleteByExpiryDateLessThan has the return type void:

select 
    *
from 
    VerificationToken verification 
where 
    verification.expiryDate < ?

select 
    * 
from
    user_account user 
where
    user.id=?

delete from 
    VerificationToken
where
    id=?

2.2. The Delete with JPQL

Alternatively, we can create a JPQL query if we do not have a need to load the entities into the persistence context:

public interface VerificationTokenRepository
  extends JpaRepository<VerificationToken, Long> {

    @Modifying
    @Query("delete from VerificationToken t where t.expiryDate <= ?1")
    void deleteAllExpiredSince(Date now);
}

And Hibernate will not load the entities into the persistence context:

delete from
    VerificationToken
where
    expiryDate <= ?

3. Scheduling a Token Purge Task

We now have a query we want to execute periodically; We’ll use the scheduling support in Spring and create a method to run our delete logic.

If you’re looking for more info on the Spring Job Scheduling framework, have a look at this article.

3.1. Enable Scheduling

To enable the scheduling of tasks we create a new configuration class SpringTaskConfig annotated with @EnableScheduling:

@Configuration
@EnableScheduling
public class SpringTaskConfig {
    //
}

3.2. Purge Token Task

In the service layer we call our repository with the current time.

We then annotate the method with @Scheduled to indicate that Spring should execute it periodically:

@Service
@Transactional
public class TokensPurgeTask {

    @Autowired
    private VerificationTokenRepository tokenRepository;

    @Scheduled(cron = "${purge.cron.expression}")
    public void purgeExpired() {
        Date now = Date.from(Instant.now());
        tokenRepository.deleteAllExpiredSince(now);
    }
}

3.3. The Schedule

We used a property to hold the value of the crontab settings to avoid recompilation when changed. In the application.properties we assign the value:

#    5am every day
purge.cron.expression=0 0 5 * * ?

4. Conclusion

In this article we solved the removal of VerificationTokens using Spring Data JPA.

We demonstrated query creation using a property expression to find all tokens having an expiration date less than a specified time. And we created a task to invoke this clean logic at runtime – and registered it with the Spring Job Scheduling framework to be executed periodically.

The implementation of this Registration with Spring Security tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

I just announced the new Spring Security 5 modules (primarily focused on OAuth2) in the course:

>> CHECK OUT LEARN SPRING SECURITY