A simple CMS using Spring Data and JPA

For this post, I’m going to create a very simple CMS which will allow the user to create an article with a headline, preview text and text body. I will use Spring JPA to persist the Article object to a database; in this case a H2 DB, and view the content using JSP and allow access to an article or the full list of articles in JSON.

I’m prototyping a nice and simple solution for websites to cleanly decouple their CMS from the web applications rendering their content. I’ll build on this application in those future posts.

I went with Spring JPA because it’s incredibly simple and reduces the amount of code and configuration with have to write. In the pom.xml for the project I’m adding dependencies for Spring JPA, H2, the hibernate enitity manager and jackson JSON mapper, which Spring will notice as if by magic  and give us a JSONified version of our entities later on for free!

	<!-- Database integration -->	

  		org.springframework.data
  		spring-data-jpa
  		1.0.3.RELEASE

  		org.hibernate
  		hibernate-entitymanager
  		4.1.1.Final

  		org.springframework
  		spring-beans
  		3.1.1.RELEASE

  		com.h2database
  		h2
  		1.3.165

  		commons-dbcp
  		commons-dbcp
  		1.4

  		org.springframework
  		spring-orm
  		3.1.1.RELEASE

	<!-- Database integration end -->	

	<!-- Jackson JSON Mapper -->

		org.codehaus.jackson
		jackson-mapper-asl
		${jackson.version}

Next we configure our data source using Apache Commons DBCP connection pool. This goes inside Spring configuration file (spring-config.xml for this application).


We add our entity bean.

	@Entity
	public class Article {

		@Id
		@GeneratedValue
		private Integer id;
		@Column( length = 40)
		private String headline;
		@Column( length = 200)
		private String previewText;
		@Column( length = 40000)
		private String fullText;

		public Article() {
		}

		public Article(String headline, String previewText, String fullText) {
			super();<code>p
			this.headline = headline;
			this.previewText = previewText;		
			this.fullText = fullText;
		}

</code>

Take note that the column lengths are set here. We could use the @NamedQuery annotation in this bean to add more complex queries. This is a nice touch as we’ve done away with the need for a hbm.xml file so the SQL query can go in here. I never did get my head around HQL and in my experience developers like to test their queries against the DB in SQL directly and dislike or distrust rewriting them to HQL.

However, it’s more powerful than that. JPA  provides a POJO based persistence model. JPA essentially provides a standardisation to the persistence methodology, allowing any persistence framework to be used underneath JPA without having to worry about too much configuration. Hibernate implements the JPA specification by creating a wrapper over the Hibernate Core. JPA can also support mongoDB using eclipseLink

Back to our application. Next we create the Entity Manager Factory from org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean. This generates an EntityManagerFactory with specific configuration, avoiding any extra files to setup the persistence layer, so we no longer need a persistence.xml nor any other mapping files.

All the JPA configuration happens in this bean declaration. The first property sets where it finds the DataSource, the bean defined earlier. The second property, packagesToScan, sets a list of packages that will be scanned for entities. The third property is the persistence provider, in this case, I’m using Hibernate’s provider.

The fourth property is a map that will be passed to the provider for configuration. The first entry in the map is Hibernate’s dialect, that’s the one for H2 databases. If the schema doesn’t exist, it will be created. The second entry requests Hibernate to update or create the database schema to match what’s being mapped in the entities. In either case, if the schema doesn’t exist, it will be created. Using ‘update’ in place or ‘create’ will persist the data outside the lifetime of the application

	
		
		
		
			
		
		


<map>
				
				
			</map>

 

Spring Data will use the following repository interface to manage all interaction with the underlying data (JPA) repository. We don’t need to implement any code. I’m extending org.springframework.data.repository.CrudRepository for now but I can change that to org.springframework.data.repository.PagingAndSortingRepository at a later date to use when adding pagination

	import org.springframework.data.repository.CrudRepository;

	public interface ArticleRepository extends CrudRepository&lt;Article, Integer&gt; 

	}

Spring Data JPA provides a specific namespace that contains one tag-do-all that will create the repository implementation for us.


The only thing I need to do is say what package my repository is in. The package – and subpackages – will be scanned for interfaces that extends Repository and an implementation will be provided. More detail of how this works can be seen here. Now we turn our attention to the Controller class.

@Controller
public class CMSController {
	@Autowired
	private ArticleRepository repository;		

	private static final Logger logger = LoggerFactory.getLogger(CMSController.class);

	@RequestMapping(value = "/createArticle", method = RequestMethod.GET)
	public ModelAndView createArticle() {
		logger.info("createArticle view - user must submit to add to DB");
	    return new ModelAndView("createArticle", "articleModel", new Article());
	}

	@RequestMapping(value = "/addArticle", method = RequestMethod.POST) 
	public String submitArticle(@ModelAttribute("Article") Article article, ModelMap model) {
		logger.info("addArticle called to add new article");
		repository.save(article);				
		model.addAttribute("articles", repository.findAll());
	    return "redirect:/home";
	}

In the RequestMapping for ‘/createArticle’ we create a new Article entity and pass it back via the ModelAttribute for the html form used to submit the new Article. The form submitted then is mapped via ‘/addArticle’.


Remember we added the jackson mapper in our pom.xml? Well we just need to add @ResponseBody to the return value for a  RequestMapping method.

	@RequestMapping(value ="/viewArticle/{id}", method = RequestMethod.GET)
	public @ResponseBody
	Article getArticleInJSON(@PathVariable Integer id) {
		return repository.findOne(id);
	}	

	@RequestMapping(value ="/viewArticles", method = RequestMethod.GET)
	public @ResponseBody
	Iterable getArticlesInJSON() { return repository.findAll(); }

When Spring sees the following;

  1. Jackson library exists in the project classpath
  2. annotation-driven is enabled in config
  3. Return method annotated with @ResponseBody

Spring will handle the JSON conversion automatically.

Code for this post is available on github here

screenshots:
home – http://localhost:8080/publisher/home – in browser
Screenshot from 2013-12-07 15:10:25

articles returned in JSON from a GET
Screenshot from 2013-12-07 15:11:29

Bookmark the permalink.

One Comment

  1. If you do clone the code you may notice that the removeArticle method is done by a POST rather than a DELETE. This is because DELETE is not available in HTML forms and I wanted to keep everything as simple as possible. I’ll be using javascript XMLHttpRequest in the next version so we’ll get rid of that code smell then!

Leave a Reply