AJAX with CKEditor in Spring Boot

1. Overview

In this article, we will cover how to use CKEditor with Spring Boot . In this tutorial, we will be importing an XML document with numerous data, program the ability to load a set of data to the CKEditor instance with a GET request, and do a POST request to save the CKEditor’s data.

Technologies we will be using include MongoDB, Thymeleaf, and Spring Batch.

The full source code for this tutorial is available on Github .

2. What is CKEditor?

CKEditor is a browser-based What-You-See-Is-What-You-Get (WYSIWYG) content editor . CKEditor aims to bring to a web interface common word processor features found in desktop editing applications like Microsoft Word and OpenOffice.

CKEditor has numerous features for end users in regards to the user interface, inserting content, authoring content, and more.

There are different versions of CKEditor, but for this tutorial we are using CKEditor 4. To see a demo, visit: https://ckeditor.com/ckeditor-4/

3. The XML Document

As mentioned, we are uploading an XML document in this application. The XML data will be inserted into the database and used for the rest of the tutorial.

 Guide to Music I Like - No Specific Genre
  This guide presents a catalog of music that can be found on Spotify. 
    This is a very small sample of music found on Spotify and is no way to be considered comprehensive.
    Run the Jewels
    Legend Has It
    Kendrick Lamar
    Weird Al Yankovic
    NOW That's What I Call Polka!
    Eiffel 65
    Blue (Da Ba Dee) - DJ Ponte Ice Pop Radio
    Hacker Music
    Raise Your Flag
    GZA, Method Man

4. Model

For the above XML code, we can model a Song like this:

public class SongModel {
    private String id;
    private String artist;
    private String songTitle;
    private Boolean updated;
    public Boolean getUpdated() {
        return updated;
    public void setUpdated(Boolean updated) {
        this.updated = updated;
    public String getArtist() {
        return artist;
    public void setArtist(String artist) {
        this.artist = artist;
    public String getSongTitle() {
        return songTitle;
    public void setSongTitle(String songTitle) {
        this.songTitle = songTitle;
    public String getId() {
        return id;
    public void setId(String id) {
        this.id = id;
    public SongModel(
        @JsonProperty("artist") String artist,
        @JsonProperty("song-title") String songTitle){
        this.artist = artist;
        this.songTitle = songTitle;
    public String toString() {
      return "Person [id=" + id + ", artist=" + artist + ", song-title=" + songTitle + "]";


For our application, we will be differentiating between an unmodified song and a song that has been modified in CKEditor with a separate Model and Repository.

Let’s now define what an Updated Song is:

public class UpdatedSong {
    private String id;
    private String artist;
    private String songTitle;
    private String html;
    private String sid;
    public String getSid() {
        return sid;
    public void setSid(String sid) {
        this.sid = sid;
    public String getId() {
        return id;
    public void setId(String id) {
        this.id = id;
    public String getArtist() {
        return artist;
    public void setArtist(String artist) {
        this.artist = artist;
    public String getSongTitle() {
        return songTitle;
    public void setSongTitle(String songTitle) {
        this.songTitle = songTitle;
    public String getHtml() {
        return html;
    public void setHtml(String html) {
        this.html = html;


5. File Upload and Processing

As this article’s focus is on CKEditor and AJAX, we aren’t going to go into detail on the file upload and processing with Spring Batch. We have reviewed this process in depth in these prior posts, however:

6. Setting Data to CKEditor – GET Request

It is our goal to retrieve the data for an individual song and display that data in CKEditor. There are two issues to tackle: retrieving the data for an individual song and displaying it in CKEditor.

6.1 Client Side Code

In view.html, we use a table in Thymeleaf to iterate through each Song in the Song repository. To be able to retrieve the data from the server for a specific song, we pass in the Song’s id to a function.

Here’s the snippet of code that is responsible for calling the function that retrieves the data from the server and subsequently sets the data to the CKEditor instance :

Artist Song Title Load
Text ... Text ...

As we can see, the id of Song is essential for us to be able to retrieve the data.

In the getSong function, we use a deferred promise to ensure that data is set after the GET request:

function getSong(song) {
				url : "/api/show/?sid=" + song,
				type : 'GET',
				dataType : 'text'
			}).then(function(data) {
				var length = data.length-2;
				var datacut = data.slice(9,length);


			$("#form").attr("action", "/api/save/?sid=" + song);


6.2 Server Side Code

getSong accepts a parameter named sid , which stands for Song id. sid is also a path variable in the @GetMapping . We treat sid as a String because this is the id of the Song from MongoDB.

We check if the Song has been modified and if so we retrieve the associated UpdatedSong entity. If not, we treat the Song differently. Ultimately, we return a simple POJO with a String for data named ResponseModel , however:

    public ResponseEntity getSong(@RequestParam String sid, Model model){
        ResponseModel response = new ResponseModel();
        System.out.println("SID :::::" + sid);
        ArrayList musicText = new ArrayList();
            String sidString = sid;
            SongModel songModel = songDAO.findOne(sidString);
            System.out.println("get status of boolean during get ::::::" + songModel.getUpdated());
            if(songModel.getUpdated()==false ){
                String filterText = format.changeJsonToHTML(musicText);
            } else if(songModel.getUpdated()==true){
                UpdatedSong updated = updatedDAO.findBysid(sidString);
                String text = updated.getHtml();
                System.out.println("getting the updated text ::::::::" + text);

        model.addAttribute("response", response);
        return ResponseEntity.ok(response);

ResponseModel is a very simple POJO as mentioned:

public class ResponseModel {
    private String data;
    public ResponseModel(){
    public ResponseModel(String data){
            this.data = data;

    public String getData() {
            return data;

    public void setData(String data) {
            this.data = data;

7. Saving CKEditor Data – POST Request

POSTing the data isn’t much of a challenge; however, ensuring that the data is handled appropriately can be.

7.1 Client Side Code

As the CKEditor instance is a textarea within a form, we can trigger a function on a form submit:

function() {

$("#form").submit(function(event) {
// Prevent the form from submitting via the browser.

ajaxPost() retrieves the current data in the CKEditor and sets it to the variable formData :

function ajaxPost() {

var formData = CKEDITOR.instances.content

type : "POST",
contentType : "text/html",
url : $("#form").attr("action"),
data : formData,
dataType : 'text',
success : function(result) {


+ "Post Successfully! "
+ "


error : function(e) {
console.log("ERROR: ", e);



It is important to note:

  • contentType is “text/html”
  • dataType is “text”

Having the incorrect contentType or dataType can lead to errors or malformed data.

7.2 Server Side Code

We stated in our contentType for the POST request that the mediatype is “text/html” . We need to specify in our mapping that this will be consumed. Therefore, we add consumes = MediaType.TEXT_HTML_VALUE with our @PostMapping .

Areas for us to note include:

  • @RequestBody String body is responsible for setting the variable body to the content of our request
  • We once again return ResponseModel , the simple POJO described earlier that contains our data
  • We treat a previously modified SongModel different than one that has not been modified before

Also, like the GET request, the sid allows us to deal with the correct Song:

@PostMapping(value={"/save/","/save/[sid]"}, consumes = MediaType.TEXT_HTML_VALUE)
    public @ResponseBody ResponseModel saveSong( @RequestBody String body, @RequestParam String sid){
        ResponseModel response = new ResponseModel();
        SongModel oldSong = songDAO.findOne(sid);
        String songTitle = oldSong.getSongTitle();
        String artistName = oldSong.getArtist();
        if(oldSong.getUpdated() == false){
            UpdatedSong updatedSong = new UpdatedSong();
            System.out.println("get status of boolean during post :::::" + oldSong.getUpdated());
            UpdatedSong currentSong = updatedDAO.findBysid(sid);
        return response;

8. Demo

We visit localhost:8080 :

We upload the provided music-example.xml file:

We click “Load” for a song:

We add content and click “Save”:

If you return to the saved content, you may see “n”for line breaks. For the time being, discussing this is out of the scope for the tutorial.

9. Conclusion

In this tutorial, we covered how to load data using a GET request with the object’s id, set the data to the CKEditor instance, and save the CKEditor’s data back to the database with a POST request. There’s extra code, such as using two different entities for the data (an original and a modified version), that isn’t necessary, but hopefully is instructive.

The full code can be found on Github .


Guns Lite基于spring boot的后台管理系统 年初公司计划要上一个产品,而且是要在两周内上线(由于之前已经开发、运营过一个类似的产品,所以这次要求先将核心功能上线;当然最后没有那么快上线,这是后话)。 由于这个系统比较复杂,所以我们和以前一样计划将服务拆分,包括后台管理、微信端,api层,消息服务,调度任务等若干服务。领导既然发话了,无论计划看...
SpringBoot 快速定时任务(附实时刷新教程)... 序言:创建定时任务非常简单,主要有两种创建方式:一、基于注解(@Scheduled) 二、基于接口(SchedulingConfigurer). 前者相信大家都很熟悉,但是实际使用中我们往往想从数据库中读取指定时间来动态执行定时任务,这时候基于接口的定时任务就大派用场了。 一、静态定时任务(基于...
Spring Boot 2.0 新特性和发展方向 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持。 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了的幅度有点大。EmbeddedServletContainer被重命名为WebServe...
Ajax (with jQuery) does not retu... I just wrote this code (just an example..): $.ajax({ type: "POST", url: "users/say_hello_id", data: {id : 1}, success:function(da...
Configuring nginx to proxy REST requests across mu... Using nginx to proxy requests across Docker containers is a common use case for nginx, and covered in many posts and articles . Trying to get it w...
责编内容来自:Java and Cyber Security Tutorials (源链) | 更多关于

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » AJAX with CKEditor in Spring Boot

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录