Creating a web site with Spring Boot, Spring Framework, Hibernate ORM and Thymeleaf

Now, if i want to get into every programmatical detail, this post would turn into a beginners course. :) But i think i can explain couple of milestones to develop a website like this using 4 fundamental + 2 complimentary technologies, all based on my experience. I might also write about different subjects in detail in the future under the Software category. Let's just take the first step for now. If you say i you are a software developer and you want to create a website by using commonly used popular technologies, here we go.

#1. Blueprint of the project (Spring Boot + Spring Framework)

Spring Framework is widely used nowadays and it is bascially changing the way we create software. It is also accelerating it when used with Spring Boot infrastructure. First thing we need is going to be a Spring Boot application. You can create a template like i showed in the image below by visiting Spring Initilizr website.

The left side of the screen contains the necessary information for Maven, which is one of the complimentary technologies. Maven will form your project and source code and compile it in a packate with these information. The packaging of your project can be "jar" file since spring boot will provide a main method and a built-in apache tomcat server inside.

#2. Dependencies

Our first dependency devtools will deploy your application on the built-in server, as soon as you save your code. This way you will not have to stop-start the application everytime you change the code. When you choode Run as -> Spring Boot Application, your website will be deployed and start serving from http://localhost:8080.

The second dependency, Lombok, is a non-obligatory library. Your code will have entities (database tables). And these entities will have to have getter, setter and constructor methods. Lombok will be injecting these methods without writing these boilerplate code over and over again. If you are going to use it Eclipse, you have to go to the Web Site and install the add-on.

The next one, Spring Web will give the necessary libraries to run as a web project. It will include an apache tomcat server inside and will run the website here. This way, you won't have to create a server manually and choose Run as -> Run on server. Insted you will be running as Spring Boot application. Spring boot will handle these operations, all the while making you ever more lazy. :)

Thymeleaf is basicaly a tag library where you can take advantage of MVD design pattern. This will enable you to convert the information into html output with spefific code structures. For example, when you use th:each command, the interpreter will turn it into a for loop and multpliy the element in the html page. It works very well with spring framework too. More on this is here.

The next dependency, Spring Security, is the access control library. It handles operations like password protections or cross site script attacks. I do not have extensive information about it but you will probably use it to secure your admin pages for the website. :)

Spring data JPA will help you query your database with codes rather than native queries. It will also boost your development process and make it easier to maintain, by allowing you to create and operate on your entities inside your code. To put it simply, less sql, more java.

MS SQL Server Driver can be replaced by other database vendors like MySql, Oracle, PostgreSql. This is the database driver (connection agent) and mssql is just an example. You can choose anyone you want. But you will inevitably use one.

#3. Backend is done but where is the frontend?

We will be taking advantage of Thymeleaf properties on the frontend. But if you can't design your own user interface with css and javascript or you are not familiar with technologies like react, angular, vue.js (like me), you might have to start with an html template here. As long as you attribute the creator in your website with a link, you can find a number of free html bootsrap (css) templates to use. I found one in ColorLib. There are mostly wordpress templates but you can also find html + bootsrap templates too.

#4. The project is ready to be developed

After you find or create a theme and include it inside the templates folder, the project should look something like the image below. Eclipse 'de Import Existing Maven Project işlemi ile tabi.

In eclipse, you should also install Spring Tools Suite from the marketplace too.

MysiteApplication class at the top is the main class which basically boots the spring boot. Resources folder will store your images, css files, javascript files inside the static folder. Thymeleaf and spring boot will be working with this structure. Templates folder will store your web pages. Notice Index.html is here. application.properties will hold the environment variable for the whole application. Database connection strigs, usernames and passwords, logging levels and ..etc will be here. pom.xml at the bottom will be used by Maven when compiling your application and will also hold the necessary depenceny information.

This project is basicaly ready to launch with Run as -> Spring Boot Application at this stage but it will look for database configuration to connect a database while launching. An example for MSSQL database connection properties inside the application.properties would be like this:

		
spring.datasource.url = jdbc://adres:port; databaseName=mysitedatabase;
spring.datasource.driverClassName = com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.username = username
spring.datasource.password = password
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.SQLServer2012Dialect
spring.security.user.name = admin
spring.security.user.password = password
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext
		
	

After writing the necessary information here, you can try to open http://localhost:8080/index.html in your browser, only to get a faceful of spring security in front of you. But you can pass this security layer by entering the spring.security.user.name and password properties in the application.properties file above. (Yes you will also get a 404 error after this but we will handle that later.)

If you are creating a blog like this, you will probably use the security for admin pages only. In order to tell spring security to intervene only for the admin pages and let the users browse other pages freely, you should include a class like this inside your application.

			
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig extends WebSecurityConfigurerAdapter
{
	@Override
	protected void configure(HttpSecurity http) throws Exception
	{
		http.authorizeRequests().antMatchers("/admin").authenticated().and().formLogin();
		http.authorizeRequests().antMatchers("/**").permitAll();
		http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
	}
}
			
		

@Configuration means this class is a configuration file for spring boot. Shocker. For example, while the royal guard of spring security is awakening, spring boot will look for beans with this annotation. When you extend WebSecurityConfigurerAdapter class, this will indicate that this is the kind of configuration class for spring security.

This will establish the basic security settings for spring security. We can now move on to prepearing the data for index.html. First, let's define the hibernate entities (database tables). A simple entity example can be like this:

		
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "POST")
public class Post
{
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "post_seq")
	@SequenceGenerator(name = "post_seq", sequenceName = "post_seq", allocationSize = 1)
	@Column(name = "ID", nullable = false)
	private int id;

	@Nationalized
	@Column(name = "TITLE", nullable = false, length = 1500)
	private String title;

	@Nationalized
	@Column(name = "CONTENT", nullable = false, length = 1000)
	private String content;

	@Nationalized
	@Column(name = "SUMMARY", nullable = false, length = 2000)
	private String summary;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "CATEGORY", referencedColumnName = "ID", nullable = false)
	private Category category;

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "post")
	@Where(clause = "active = 1")
	private List<Comment> comments;

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "post_tags", joinColumns = @JoinColumn(name = "post_ID"), inverseJoinColumns = @JoinColumn(name = "TAG_ID"))
	private List<Tag> tags;

	@Column(name = "PUB_DATE", nullable = false)
	private Date publish_date = new Date();
}
		
	

@Entity will let the spring boot know that this class should be treated as an entity, not like person or animal or something. @Getter, @Setter, @AllArgsConstructor, @NoArgsConstructor is perks of Lombok and these methods are injected while packaging. Thus getting rid of the boilerplate code. @Table annotation will indicate the database table name. This is the best practice.

There are also joins here that i have added as clues for you. This database structure is completely up to you but i wanted to give n-1 Category, n-n Tag and 1-n Comment classes as example. There is no necessity to go further details here since you will probably have a different approach.

@Nationalized annotation will solve the nationalized character problem in MSSQL. Now we need to write a database access method somewhere. Assuming you insert the first post inside your databse manually, i can give you a simple database access class like this:

		
@Repository
public class SiteRepository
{
	private EntityManager em;

	@Autowired
	public SiteRepository(EntityManagerFactory factory)
	{
		this.em = factory.createEntityManager();
	}
	public List<Post> get_all_posts()
	{
		List<Post> res = null;
		Session session = em.unwrap(Session.class);
		CriteriaBuilder builder = session.getCriteriaBuilder();
		CriteriaQuery<Post> criteria_query = builder.createQuery(Post.class);
		Root<Post> root = criteria_query.from(Post.class);
		criteria_query.orderBy(builder.desc(root.get("publish_date")));
		Query<Post> query = session.createQuery(criteria_query);
		res = query.getResultList();
		return res;
	}
}
		
	

@Repository is a spring framework stereotype annotation just like @Component or @Service. @Repository is the go to annotation for database operation classes. With the help of @CriteriaQuery, this example is selecting all the posts from Post table. Also ordering the result descending by publish_date column. Criteria query classes are now used since the Criteria API is deprecated. And EntityManager is provividing an unwrap method to create a database session.

Now you can actually try to go /index.html page but you will get a 404 error. You must provide a router here and you will be using controller classes of spring framework. There is also database queries here with our ready to use repository and entitiy classes. ModelAndView class will tell spring framework to prepare the index.html page (view) with the list of posts as extra information (model). Example:

		
@Controller
public class Maincontroller
{
	private SiteRepository repository;

	private List<Post> all_posts;

	@Autowired
	public Maincontroller(SiteRepository post_repository)
	{
		this.repository = post_repository;
		this.all_posts = this.repository.get_all_posts();
	}
	@GetMapping(path =
	{ "", "index", "index.html" })
	public ModelAndView home()
	{
		ModelAndView modelAndView = new ModelAndView("index");
		modelAndView.addObject("posts", this.all_posts);
		return modelAndView;
	}
}
		
	

Spring boot will instantiate this class as a bean and use it to match web requests with views because it is annotated with @Controller annotation. @Autowired is basicaly telling spring boot to find a bean with SiteRepository type and inject it to the constructor on the boot time. @GetMapping is a web get request annotation that indicates this method will be responding to / or /index or /index.html requests. The necessary back-end code for index.html is ready at this stage.

The only step left to put these posts on the interface is to use thymeleaf specifications. You can use a structure like th:each on the frontend like this:

			
<div th:each="post: ${posts}">
	<a th:href="@{'post?id=' + ${post.id}}" th:text="${post.title}"></a>
</div>
			
		

#5. I taught you how to fish rather than giving you the fish

The first page where you may list your blog posts can be prepared with these couple of classes and code blocks. You must continue your journey by configuring, managing and implementing your own requirements after this point. You can get these codes to work in only 1 day with some experience. If you already know what kind of website are you going to develop, you will mostly using similar codes with spring, hibernate and thymeleaf. Your Controller class will eventually get bigger. The data you store in the database will evolve hence making complex repository classes. The purpose of this post is to give you the basics and guide you through the first baby steps. I wish you error-free coding and see you at the next post :)


Leave a comment