In one of my previous posts I described a blog engine I was developing. At the time, I had returned to it after a hiatus and I was convinced I would continue working on it. However, at the same time I was still more interested in developing my python-based url-shortener project and I also already planned moving on to other projects and technologies. As a result, I got bored of blog-engine again.
Since then, I’ve been focusing on Java and Spring Framework. This resulted in a new project: another blog engine, but this time based on Spring and designed with different features.
Ideas and features
I decided this blog engine will be simpler than the previous one (at least initially) and will have the following features:
- a support for a single administrator and blog author
- configuration based on editing files rather than using a graphical user interface
- dynamically generated menus used for main navigation element, blogroll widget, etc.
- autopublication of articles on selected dates
I chose Spring Boot for the base of my project because I wanted to rely on its starters and simplified configuration and also because that was the advice I’ve read in a number of posts (for example, here).
I named my previous blog engine project simply “blog-engine”. Not very imaginative, but still unique when compounded with my GitHub username. Choosing the same name for another project is not very practical (not to mention: impossible on GitHub), so I had to pick something else. Since I started the project shortly before Christmas, I decided to name it Yule, after a historical pagan germanic festival observed near the same time of the year.
Article entity class
For storing and transfering article data, I initally wanted to implement two classes:
- a database entity class. Since Hibernate ORM, a JPA implementation I’m using, can use reflection to access fields of entity objects and only requires a no-argument constructor of any visibility, I could write this class so that it would be properly encapsulated, that is: in a way ensuring all constructor and method calls would result in a valid article object, or in an exception being thrown.
- a form-backing class. Thymeleaf, a template engine I decided to use, requires such classes to have getter and setter method for each field included in a form. This class would be allowed to contain data that would be invalid for an article.
However, after some time, I decided to combine the two roles in the database entity class. After all, this is a simpler solution and instances of such a class may still be validated, no matter the source of their potentially invalid state.
Standard and custom validation constraints
Some validation constraints are applied to specific fields of each article object, regardless of its current state. For example, each article requires a non-empty title. For such constraints, annotations and validators built into JBV (like
NotNull) or Hibernate Validator (like
NotBlank) are enough.
Other constraints are applied to articles only with specific statuses: objects representing life cycle stages of individual articles, implemented as instances of
ArticleStatus enum. For example, published articles accept only a non-future publication date, the ones scheduled for auto-publication require a future one, while drafts accept any publication date, including none at all. Both published and scheduled articles require a content that is not blank, while drafts have no such requirement.
Because of this dependance of constraints of some fields on value of another field, I had to define a custom, cross-field, class-level constraint and implement a validator for it.
Since these constraints are dependent on a particular value of
ArticleStatus and occur in different combinations, I decided to implement them as optional dependencies of
ArticleStatus objects. They are instances of classes extending a common abstract superclass:
ExistingArticleConstraint, and providing a constraint-testing method, an error message template and a name of a field to which the message applies.
Article class has a
getViolatedStatusConstraints() method validating constraints provided by the current status of an article and returning those constraints that aren’t fulfilled by it. This method is called by my custom constraint validator class. Objects representing violated status constraints are returned by the method and then are used by the validator to build constraint violations, assigning proper error messages to fields for which the constraints were violated.
I think that’s enough for this post. In the next one, I will describe the service layer of the project.